/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 at bsnet
  • Date: 2010-09-21 19:16:41 UTC
  • Revision ID: teddy@fukt.bsnet.se-20100921191641-yetps84gvjo7hrrc
* mandos-ctl.xml: New.
* Makefile (DOCS): Added "mandos-ctl.8".
  (mandos-ctl.8): New.

Show diffs side-by-side

added added

removed removed

Lines of Context:
83
83
 
84
84
version = "1.0.14"
85
85
 
 
86
#logger = logging.getLogger(u'mandos')
86
87
logger = logging.Logger(u'mandos')
87
88
syslogger = (logging.handlers.SysLogHandler
88
89
             (facility = logging.handlers.SysLogHandler.LOG_DAEMON,
156
157
                            u" after %i retries, exiting.",
157
158
                            self.rename_count)
158
159
            raise AvahiServiceError(u"Too many renames")
159
 
        self.name = self.server.GetAlternativeServiceName(self.name)
 
160
        self.name = unicode(self.server.GetAlternativeServiceName(self.name))
160
161
        logger.info(u"Changing Zeroconf service name to %r ...",
161
 
                    unicode(self.name))
 
162
                    self.name)
162
163
        syslogger.setFormatter(logging.Formatter
163
164
                               (u'Mandos (%s) [%%(process)d]:'
164
165
                                u' %%(levelname)s: %%(message)s'
165
166
                                % self.name))
166
167
        self.remove()
167
 
        self.add()
 
168
        try:
 
169
            self.add()
 
170
        except dbus.exceptions.DBusException, error:
 
171
            logger.critical(u"DBusException: %s", error)
 
172
            self.cleanup()
 
173
            os._exit(1)
168
174
        self.rename_count += 1
169
175
    def remove(self):
170
176
        """Derived from the Avahi example code"""
193
199
        self.group.Commit()
194
200
    def entry_group_state_changed(self, state, error):
195
201
        """Derived from the Avahi example code"""
196
 
        logger.debug(u"Avahi state change: %i", state)
 
202
        logger.debug(u"Avahi entry group state change: %i", state)
197
203
        
198
204
        if state == avahi.ENTRY_GROUP_ESTABLISHED:
199
205
            logger.debug(u"Zeroconf service established.")
212
218
            self.group = None
213
219
    def server_state_changed(self, state):
214
220
        """Derived from the Avahi example code"""
 
221
        logger.debug(u"Avahi server state change: %i", state)
215
222
        if state == avahi.SERVER_COLLISION:
216
223
            logger.error(u"Zeroconf server name collision")
217
224
            self.remove()
258
265
                     runtime with vars(self) as dict, so that for
259
266
                     instance %(name)s can be used in the command.
260
267
    current_checker_command: string; current running checker_command
261
 
    approved_delay: datetime.timedelta(); Time to wait for approval
 
268
    approval_delay: datetime.timedelta(); Time to wait for approval
262
269
    _approved:   bool(); 'None' if not yet approved/disapproved
263
 
    approved_duration: datetime.timedelta(); Duration of one approval
 
270
    approval_duration: datetime.timedelta(); Duration of one approval
264
271
    """
265
272
    
266
273
    @staticmethod
278
285
        "Return the 'interval' attribute in milliseconds"
279
286
        return self._timedelta_to_milliseconds(self.interval)
280
287
 
281
 
    def approved_delay_milliseconds(self):
282
 
        return self._timedelta_to_milliseconds(self.approved_delay)
 
288
    def approval_delay_milliseconds(self):
 
289
        return self._timedelta_to_milliseconds(self.approval_delay)
283
290
    
284
291
    def __init__(self, name = None, disable_hook=None, config=None):
285
292
        """Note: the 'checker' key in 'config' sets the
303
310
                      "rb") as secfile:
304
311
                self.secret = secfile.read()
305
312
        else:
306
 
            #XXX Need to allow secret on demand!
307
313
            raise TypeError(u"No secret or secfile for client %s"
308
314
                            % self.name)
309
315
        self.host = config.get(u"host", u"")
321
327
        self.checker_command = config[u"checker"]
322
328
        self.current_checker_command = None
323
329
        self.last_connect = None
 
330
        self._approved = None
 
331
        self.approved_by_default = config.get(u"approved_by_default",
 
332
                                              True)
324
333
        self.approvals_pending = 0
325
 
        self._approved = None
326
 
        self.approved_by_default = config.get(u"approved_by_default",
327
 
                                              False)
328
 
        self.approved_delay = string_to_delta(
329
 
            config[u"approved_delay"])
330
 
        self.approved_duration = string_to_delta(
331
 
            config[u"approved_duration"])
 
334
        self.approval_delay = string_to_delta(
 
335
            config[u"approval_delay"])
 
336
        self.approval_duration = string_to_delta(
 
337
            config[u"approval_duration"])
332
338
        self.changedstate = multiprocessing_manager.Condition(multiprocessing_manager.Lock())
333
 
 
 
339
    
334
340
    def send_changedstate(self):
335
341
        self.changedstate.acquire()
336
342
        self.changedstate.notify_all()
700
706
    # dbus.service.Object doesn't use super(), so we can't either.
701
707
    
702
708
    def __init__(self, bus = None, *args, **kwargs):
 
709
        self._approvals_pending = 0
703
710
        self.bus = bus
704
711
        Client.__init__(self, *args, **kwargs)
705
712
        # Only now, when this client is initialized, can it show up on
709
716
                                  + self.name.replace(u".", u"_")))
710
717
        DBusObjectWithProperties.__init__(self, self.bus,
711
718
                                          self.dbus_object_path)
 
719
        
 
720
    def _get_approvals_pending(self):
 
721
        return self._approvals_pending
 
722
    def _set_approvals_pending(self, value):
 
723
        old_value = self._approvals_pending
 
724
        self._approvals_pending = value
 
725
        bval = bool(value)
 
726
        if (hasattr(self, "dbus_object_path")
 
727
            and bval is not bool(old_value)):
 
728
            dbus_bool = dbus.Boolean(bval, variant_level=1)
 
729
            self.PropertyChanged(dbus.String(u"ApprovalPending"),
 
730
                                 dbus_bool)
 
731
 
 
732
    approvals_pending = property(_get_approvals_pending,
 
733
                                 _set_approvals_pending)
 
734
    del _get_approvals_pending, _set_approvals_pending
712
735
    
713
736
    @staticmethod
714
737
    def _datetime_to_dbus(dt, variant_level=0):
721
744
        r = Client.enable(self)
722
745
        if oldstate != self.enabled:
723
746
            # Emit D-Bus signals
724
 
            self.PropertyChanged(dbus.String(u"enabled"),
 
747
            self.PropertyChanged(dbus.String(u"Enabled"),
725
748
                                 dbus.Boolean(True, variant_level=1))
726
749
            self.PropertyChanged(
727
 
                dbus.String(u"last_enabled"),
 
750
                dbus.String(u"LastEnabled"),
728
751
                self._datetime_to_dbus(self.last_enabled,
729
752
                                       variant_level=1))
730
753
        return r
734
757
        r = Client.disable(self, quiet=quiet)
735
758
        if not quiet and oldstate != self.enabled:
736
759
            # Emit D-Bus signal
737
 
            self.PropertyChanged(dbus.String(u"enabled"),
 
760
            self.PropertyChanged(dbus.String(u"Enabled"),
738
761
                                 dbus.Boolean(False, variant_level=1))
739
762
        return r
740
763
    
752
775
        self.checker_callback_tag = None
753
776
        self.checker = None
754
777
        # Emit D-Bus signal
755
 
        self.PropertyChanged(dbus.String(u"checker_running"),
 
778
        self.PropertyChanged(dbus.String(u"CheckerRunning"),
756
779
                             dbus.Boolean(False, variant_level=1))
757
780
        if os.WIFEXITED(condition):
758
781
            exitstatus = os.WEXITSTATUS(condition)
773
796
        r = Client.checked_ok(self, *args, **kwargs)
774
797
        # Emit D-Bus signal
775
798
        self.PropertyChanged(
776
 
            dbus.String(u"last_checked_ok"),
 
799
            dbus.String(u"LastCheckedOK"),
777
800
            (self._datetime_to_dbus(self.last_checked_ok,
778
801
                                    variant_level=1)))
779
802
        return r
791
814
            # Emit D-Bus signal
792
815
            self.CheckerStarted(self.current_checker_command)
793
816
            self.PropertyChanged(
794
 
                dbus.String(u"checker_running"),
 
817
                dbus.String(u"CheckerRunning"),
795
818
                dbus.Boolean(True, variant_level=1))
796
819
        return r
797
820
    
800
823
        r = Client.stop_checker(self, *args, **kwargs)
801
824
        if (old_checker is not None
802
825
            and getattr(self, u"checker", None) is None):
803
 
            self.PropertyChanged(dbus.String(u"checker_running"),
 
826
            self.PropertyChanged(dbus.String(u"CheckerRunning"),
804
827
                                 dbus.Boolean(False, variant_level=1))
805
828
        return r
806
829
 
809
832
        return False
810
833
    
811
834
    def approve(self, value=True):
 
835
        self.send_changedstate()
812
836
        self._approved = value
813
 
        gobject.timeout_add(self._timedelta_to_milliseconds(self.approved_duration, self._reset_approved))
814
 
 
815
 
    def approved_pending(self):
816
 
        return self.approvals_pending > 0
817
 
 
 
837
        gobject.timeout_add(self._timedelta_to_milliseconds
 
838
                            (self.approval_duration),
 
839
                            self._reset_approved)
 
840
    
818
841
    
819
842
    ## D-Bus methods, signals & properties
820
843
    _interface = u"se.bsnet.fukt.Mandos.Client"
840
863
        pass
841
864
    
842
865
    # GotSecret - signal
843
 
    # Is sent after succesfull transfer of secret from mandos-server to mandos-client
844
866
    @dbus.service.signal(_interface)
845
867
    def GotSecret(self):
846
 
        "D-Bus signal"
 
868
        """D-Bus signal
 
869
        Is sent after a successful transfer of secret from the Mandos
 
870
        server to mandos-client
 
871
        """
847
872
        pass
848
873
    
849
874
    # Rejected - signal
853
878
        pass
854
879
    
855
880
    # NeedApproval - signal
856
 
    @dbus.service.signal(_interface, signature=u"db")
 
881
    @dbus.service.signal(_interface, signature=u"tb")
857
882
    def NeedApproval(self, timeout, default):
858
883
        "D-Bus signal"
859
884
        pass
895
920
    
896
921
    ## Properties
897
922
    
898
 
    # approved_pending - property
 
923
    # ApprovalPending - property
899
924
    @dbus_service_property(_interface, signature=u"b", access=u"read")
900
 
    def approved_pending_dbus_property(self):
901
 
        return dbus.Boolean(self.approved_pending())
 
925
    def ApprovalPending_dbus_property(self):
 
926
        return dbus.Boolean(bool(self.approvals_pending))
902
927
    
903
 
    # approved_by_default - property
 
928
    # ApprovedByDefault - property
904
929
    @dbus_service_property(_interface, signature=u"b",
905
930
                           access=u"readwrite")
906
 
    def approved_by_default_dbus_property(self):
907
 
        return dbus.Boolean(self.approved_by_default)
908
 
    
909
 
    # approved_delay - property
910
 
    @dbus_service_property(_interface, signature=u"t",
911
 
                           access=u"readwrite")
912
 
    def approved_delay_dbus_property(self):
913
 
        return dbus.UInt64(self.approved_delay_milliseconds())
914
 
    
915
 
    # approved_duration - property
916
 
    @dbus_service_property(_interface, signature=u"t",
917
 
                           access=u"readwrite")
918
 
    def approved_duration_dbus_property(self):
919
 
        return dbus.UInt64(self._timedelta_to_milliseconds(
920
 
                self.approved_duration))
921
 
    
922
 
    # name - property
 
931
    def ApprovedByDefault_dbus_property(self, value=None):
 
932
        if value is None:       # get
 
933
            return dbus.Boolean(self.approved_by_default)
 
934
        self.approved_by_default = bool(value)
 
935
        # Emit D-Bus signal
 
936
        self.PropertyChanged(dbus.String(u"ApprovedByDefault"),
 
937
                             dbus.Boolean(value, variant_level=1))
 
938
    
 
939
    # ApprovalDelay - property
 
940
    @dbus_service_property(_interface, signature=u"t",
 
941
                           access=u"readwrite")
 
942
    def ApprovalDelay_dbus_property(self, value=None):
 
943
        if value is None:       # get
 
944
            return dbus.UInt64(self.approval_delay_milliseconds())
 
945
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
 
946
        # Emit D-Bus signal
 
947
        self.PropertyChanged(dbus.String(u"ApprovalDelay"),
 
948
                             dbus.UInt64(value, variant_level=1))
 
949
    
 
950
    # ApprovalDuration - property
 
951
    @dbus_service_property(_interface, signature=u"t",
 
952
                           access=u"readwrite")
 
953
    def ApprovalDuration_dbus_property(self, value=None):
 
954
        if value is None:       # get
 
955
            return dbus.UInt64(self._timedelta_to_milliseconds(
 
956
                    self.approval_duration))
 
957
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
 
958
        # Emit D-Bus signal
 
959
        self.PropertyChanged(dbus.String(u"ApprovalDuration"),
 
960
                             dbus.UInt64(value, variant_level=1))
 
961
    
 
962
    # Name - property
923
963
    @dbus_service_property(_interface, signature=u"s", access=u"read")
924
 
    def name_dbus_property(self):
 
964
    def Name_dbus_property(self):
925
965
        return dbus.String(self.name)
926
966
    
927
 
    # fingerprint - property
 
967
    # Fingerprint - property
928
968
    @dbus_service_property(_interface, signature=u"s", access=u"read")
929
 
    def fingerprint_dbus_property(self):
 
969
    def Fingerprint_dbus_property(self):
930
970
        return dbus.String(self.fingerprint)
931
971
    
932
 
    # host - property
 
972
    # Host - property
933
973
    @dbus_service_property(_interface, signature=u"s",
934
974
                           access=u"readwrite")
935
 
    def host_dbus_property(self, value=None):
 
975
    def Host_dbus_property(self, value=None):
936
976
        if value is None:       # get
937
977
            return dbus.String(self.host)
938
978
        self.host = value
939
979
        # Emit D-Bus signal
940
 
        self.PropertyChanged(dbus.String(u"host"),
 
980
        self.PropertyChanged(dbus.String(u"Host"),
941
981
                             dbus.String(value, variant_level=1))
942
982
    
943
 
    # created - property
 
983
    # Created - property
944
984
    @dbus_service_property(_interface, signature=u"s", access=u"read")
945
 
    def created_dbus_property(self):
 
985
    def Created_dbus_property(self):
946
986
        return dbus.String(self._datetime_to_dbus(self.created))
947
987
    
948
 
    # last_enabled - property
 
988
    # LastEnabled - property
949
989
    @dbus_service_property(_interface, signature=u"s", access=u"read")
950
 
    def last_enabled_dbus_property(self):
 
990
    def LastEnabled_dbus_property(self):
951
991
        if self.last_enabled is None:
952
992
            return dbus.String(u"")
953
993
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
954
994
    
955
 
    # enabled - property
 
995
    # Enabled - property
956
996
    @dbus_service_property(_interface, signature=u"b",
957
997
                           access=u"readwrite")
958
 
    def enabled_dbus_property(self, value=None):
 
998
    def Enabled_dbus_property(self, value=None):
959
999
        if value is None:       # get
960
1000
            return dbus.Boolean(self.enabled)
961
1001
        if value:
963
1003
        else:
964
1004
            self.disable()
965
1005
    
966
 
    # last_checked_ok - property
 
1006
    # LastCheckedOK - property
967
1007
    @dbus_service_property(_interface, signature=u"s",
968
1008
                           access=u"readwrite")
969
 
    def last_checked_ok_dbus_property(self, value=None):
 
1009
    def LastCheckedOK_dbus_property(self, value=None):
970
1010
        if value is not None:
971
1011
            self.checked_ok()
972
1012
            return
975
1015
        return dbus.String(self._datetime_to_dbus(self
976
1016
                                                  .last_checked_ok))
977
1017
    
978
 
    # timeout - property
 
1018
    # Timeout - property
979
1019
    @dbus_service_property(_interface, signature=u"t",
980
1020
                           access=u"readwrite")
981
 
    def timeout_dbus_property(self, value=None):
 
1021
    def Timeout_dbus_property(self, value=None):
982
1022
        if value is None:       # get
983
1023
            return dbus.UInt64(self.timeout_milliseconds())
984
1024
        self.timeout = datetime.timedelta(0, 0, 0, value)
985
1025
        # Emit D-Bus signal
986
 
        self.PropertyChanged(dbus.String(u"timeout"),
 
1026
        self.PropertyChanged(dbus.String(u"Timeout"),
987
1027
                             dbus.UInt64(value, variant_level=1))
988
1028
        if getattr(self, u"disable_initiator_tag", None) is None:
989
1029
            return
1003
1043
            self.disable_initiator_tag = (gobject.timeout_add
1004
1044
                                          (time_to_die, self.disable))
1005
1045
    
1006
 
    # interval - property
 
1046
    # Interval - property
1007
1047
    @dbus_service_property(_interface, signature=u"t",
1008
1048
                           access=u"readwrite")
1009
 
    def interval_dbus_property(self, value=None):
 
1049
    def Interval_dbus_property(self, value=None):
1010
1050
        if value is None:       # get
1011
1051
            return dbus.UInt64(self.interval_milliseconds())
1012
1052
        self.interval = datetime.timedelta(0, 0, 0, value)
1013
1053
        # Emit D-Bus signal
1014
 
        self.PropertyChanged(dbus.String(u"interval"),
 
1054
        self.PropertyChanged(dbus.String(u"Interval"),
1015
1055
                             dbus.UInt64(value, variant_level=1))
1016
1056
        if getattr(self, u"checker_initiator_tag", None) is None:
1017
1057
            return
1021
1061
                                      (value, self.start_checker))
1022
1062
        self.start_checker()    # Start one now, too
1023
1063
 
1024
 
    # checker - property
 
1064
    # Checker - property
1025
1065
    @dbus_service_property(_interface, signature=u"s",
1026
1066
                           access=u"readwrite")
1027
 
    def checker_dbus_property(self, value=None):
 
1067
    def Checker_dbus_property(self, value=None):
1028
1068
        if value is None:       # get
1029
1069
            return dbus.String(self.checker_command)
1030
1070
        self.checker_command = value
1031
1071
        # Emit D-Bus signal
1032
 
        self.PropertyChanged(dbus.String(u"checker"),
 
1072
        self.PropertyChanged(dbus.String(u"Checker"),
1033
1073
                             dbus.String(self.checker_command,
1034
1074
                                         variant_level=1))
1035
1075
    
1036
 
    # checker_running - property
 
1076
    # CheckerRunning - property
1037
1077
    @dbus_service_property(_interface, signature=u"b",
1038
1078
                           access=u"readwrite")
1039
 
    def checker_running_dbus_property(self, value=None):
 
1079
    def CheckerRunning_dbus_property(self, value=None):
1040
1080
        if value is None:       # get
1041
1081
            return dbus.Boolean(self.checker is not None)
1042
1082
        if value:
1044
1084
        else:
1045
1085
            self.stop_checker()
1046
1086
    
1047
 
    # object_path - property
 
1087
    # ObjectPath - property
1048
1088
    @dbus_service_property(_interface, signature=u"o", access=u"read")
1049
 
    def object_path_dbus_property(self):
 
1089
    def ObjectPath_dbus_property(self):
1050
1090
        return self.dbus_object_path # is already a dbus.ObjectPath
1051
1091
    
1052
 
    # secret = property
 
1092
    # Secret = property
1053
1093
    @dbus_service_property(_interface, signature=u"ay",
1054
1094
                           access=u"write", byte_arrays=True)
1055
 
    def secret_dbus_property(self, value):
 
1095
    def Secret_dbus_property(self, value):
1056
1096
        self.secret = str(value)
1057
1097
    
1058
1098
    del _interface
1156
1196
                except KeyError:
1157
1197
                    return
1158
1198
                
1159
 
                if client.approved_delay:
1160
 
                    delay = client.approved_delay
 
1199
                if client.approval_delay:
 
1200
                    delay = client.approval_delay
1161
1201
                    client.approvals_pending += 1
1162
1202
                    approval_required = True
1163
1203
                
1170
1210
                            client.Rejected("Disabled")                    
1171
1211
                        return
1172
1212
                    
1173
 
                    if client._approved or not client.approved_delay:
 
1213
                    if client._approved or not client.approval_delay:
1174
1214
                        #We are approved or approval is disabled
1175
1215
                        break
1176
1216
                    elif client._approved is None:
1177
 
                        logger.info(u"Client %s need approval",
 
1217
                        logger.info(u"Client %s needs approval",
1178
1218
                                    client.name)
1179
1219
                        if self.server.use_dbus:
1180
1220
                            # Emit D-Bus signal
1181
1221
                            client.NeedApproval(
1182
 
                                client.approved_delay_milliseconds(),
 
1222
                                client.approval_delay_milliseconds(),
1183
1223
                                client.approved_by_default)
1184
1224
                    else:
1185
1225
                        logger.warning(u"Client %s was not approved",
1186
1226
                                       client.name)
1187
1227
                        if self.server.use_dbus:
1188
1228
                            # Emit D-Bus signal
1189
 
                            client.Rejected("Disapproved")
 
1229
                            client.Rejected("Denied")
1190
1230
                        return
1191
1231
                    
1192
1232
                    #wait until timeout or approved
1203
1243
                                           client.name)
1204
1244
                            if self.server.use_dbus:
1205
1245
                                # Emit D-Bus signal
1206
 
                                client.Rejected("Time out")
 
1246
                                client.Rejected("Approval timed out")
1207
1247
                            return
1208
1248
                        else:
1209
1249
                            break
1212
1252
                
1213
1253
                sent_size = 0
1214
1254
                while sent_size < len(client.secret):
1215
 
                    # XXX handle session exception
1216
 
                    sent = session.send(client.secret[sent_size:])
 
1255
                    try:
 
1256
                        sent = session.send(client.secret[sent_size:])
 
1257
                    except (gnutls.errors.GNUTLSError), error:
 
1258
                        logger.warning("gnutls send failed")
 
1259
                        return
1217
1260
                    logger.debug(u"Sent: %d, remaining: %d",
1218
1261
                                 sent, len(client.secret)
1219
1262
                                 - (sent_size + sent))
1229
1272
            finally:
1230
1273
                if approval_required:
1231
1274
                    client.approvals_pending -= 1
1232
 
                session.bye()
 
1275
                try:
 
1276
                    session.bye()
 
1277
                except (gnutls.errors.GNUTLSError), error:
 
1278
                    logger.warning("GnuTLS bye failed")
1233
1279
    
1234
1280
    @staticmethod
1235
1281
    def peer_certificate(session):
1322
1368
              self).process_request(request, client_address)
1323
1369
        self.child_pipe.close()
1324
1370
        self.add_pipe(parent_pipe)
1325
 
        
 
1371
 
1326
1372
    def add_pipe(self, parent_pipe):
1327
1373
        """Dummy function; override as necessary"""
1328
1374
        pass
1441
1487
                                       for cond, name in
1442
1488
                                       condition_names.iteritems()
1443
1489
                                       if cond & condition)
1444
 
        logger.debug(u"Handling IPC: FD = %d, condition = %s", source,
1445
 
                     conditions_string)
1446
 
 
1447
1490
        # error or the other end of multiprocessing.Pipe has closed
1448
 
        if condition & gobject.IO_HUP or condition & gobject.IO_ERR:
 
1491
        if condition & (gobject.IO_ERR | condition & gobject.IO_HUP):
1449
1492
            return False
1450
1493
        
1451
1494
        # Read a request from the child
1452
1495
        request = parent_pipe.recv()
1453
 
        logger.debug(u"IPC request: %s", repr(request))
1454
1496
        command = request[0]
1455
1497
        
1456
1498
        if command == 'init':
1491
1533
                parent_pipe.send(('function',))
1492
1534
            else:
1493
1535
                parent_pipe.send(('data', client_object.__getattribute__(attrname)))
1494
 
 
 
1536
        
1495
1537
        if command == 'setattr':
1496
1538
            attrname = request[1]
1497
1539
            value = request[2]
1498
1540
            setattr(client_object, attrname, value)
1499
 
            
 
1541
 
1500
1542
        return True
1501
1543
 
1502
1544
 
1605
1647
    parser.add_option("--debug", action=u"store_true",
1606
1648
                      help=u"Debug mode; run in foreground and log to"
1607
1649
                      u" terminal")
 
1650
    parser.add_option("--debuglevel", type=u"string", metavar="Level",
 
1651
                      help=u"Debug level for stdout output")
1608
1652
    parser.add_option("--priority", type=u"string", help=u"GnuTLS"
1609
1653
                      u" priority string (see GnuTLS documentation)")
1610
1654
    parser.add_option("--servicename", type=u"string",
1635
1679
                        u"servicename": u"Mandos",
1636
1680
                        u"use_dbus": u"True",
1637
1681
                        u"use_ipv6": u"True",
 
1682
                        u"debuglevel": u"",
1638
1683
                        }
1639
1684
    
1640
1685
    # Parse config file for server-global settings
1657
1702
    # options, if set.
1658
1703
    for option in (u"interface", u"address", u"port", u"debug",
1659
1704
                   u"priority", u"servicename", u"configdir",
1660
 
                   u"use_dbus", u"use_ipv6"):
 
1705
                   u"use_dbus", u"use_ipv6", u"debuglevel"):
1661
1706
        value = getattr(options, option)
1662
1707
        if value is not None:
1663
1708
            server_settings[option] = value
1672
1717
    
1673
1718
    # For convenience
1674
1719
    debug = server_settings[u"debug"]
 
1720
    debuglevel = server_settings[u"debuglevel"]
1675
1721
    use_dbus = server_settings[u"use_dbus"]
1676
1722
    use_ipv6 = server_settings[u"use_ipv6"]
1677
 
    
1678
 
    if not debug:
1679
 
        syslogger.setLevel(logging.WARNING)
1680
 
        console.setLevel(logging.WARNING)
1681
 
    
 
1723
 
1682
1724
    if server_settings[u"servicename"] != u"Mandos":
1683
1725
        syslogger.setFormatter(logging.Formatter
1684
1726
                               (u'Mandos (%s) [%%(process)d]:'
1690
1732
                        u"interval": u"5m",
1691
1733
                        u"checker": u"fping -q -- %%(host)s",
1692
1734
                        u"host": u"",
1693
 
                        u"approved_delay": u"5m",
1694
 
                        u"approved_duration": u"1s",
 
1735
                        u"approval_delay": u"0s",
 
1736
                        u"approval_duration": u"1s",
1695
1737
                        }
1696
1738
    client_config = configparser.SafeConfigParser(client_defaults)
1697
1739
    client_config.read(os.path.join(server_settings[u"configdir"],
1703
1745
    tcp_server = MandosServer((server_settings[u"address"],
1704
1746
                               server_settings[u"port"]),
1705
1747
                              ClientHandler,
1706
 
                              interface=server_settings[u"interface"],
 
1748
                              interface=(server_settings[u"interface"]
 
1749
                                         or None),
1707
1750
                              use_ipv6=use_ipv6,
1708
1751
                              gnutls_priority=
1709
1752
                              server_settings[u"priority"],
1735
1778
        if error[0] != errno.EPERM:
1736
1779
            raise error
1737
1780
    
1738
 
    # Enable all possible GnuTLS debugging
 
1781
    if not debug and not debuglevel:
 
1782
        syslogger.setLevel(logging.WARNING)
 
1783
        console.setLevel(logging.WARNING)
 
1784
    if debuglevel:
 
1785
        level = getattr(logging, debuglevel.upper())
 
1786
        syslogger.setLevel(level)
 
1787
        console.setLevel(level)
 
1788
 
1739
1789
    if debug:
 
1790
        # Enable all possible GnuTLS debugging
 
1791
        
1740
1792
        # "Use a log level over 10 to enable all debugging options."
1741
1793
        # - GnuTLS manual
1742
1794
        gnutls.library.functions.gnutls_global_set_log_level(11)
1747
1799
        
1748
1800
        (gnutls.library.functions
1749
1801
         .gnutls_global_set_log_function(debug_gnutls))
 
1802
        
 
1803
        # Redirect stdin so all checkers get /dev/null
 
1804
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
 
1805
        os.dup2(null, sys.stdin.fileno())
 
1806
        if null > 2:
 
1807
            os.close(null)
 
1808
    else:
 
1809
        # No console logging
 
1810
        logger.removeHandler(console)
 
1811
    
1750
1812
    
1751
1813
    global main_loop
1752
1814
    # From the Avahi example code
1771
1833
        service.interface = (if_nametoindex
1772
1834
                             (str(server_settings[u"interface"])))
1773
1835
 
 
1836
    if not debug:
 
1837
        # Close all input and output, do double fork, etc.
 
1838
        daemon()
 
1839
        
1774
1840
    global multiprocessing_manager
1775
1841
    multiprocessing_manager = multiprocessing.Manager()
1776
1842
    
1796
1862
            for section in client_config.sections()))
1797
1863
    if not tcp_server.clients:
1798
1864
        logger.warning(u"No clients defined")
1799
 
    
1800
 
    if debug:
1801
 
        # Redirect stdin so all checkers get /dev/null
1802
 
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
1803
 
        os.dup2(null, sys.stdin.fileno())
1804
 
        if null > 2:
1805
 
            os.close(null)
1806
 
    else:
1807
 
        # No console logging
1808
 
        logger.removeHandler(console)
1809
 
        # Close all input and output, do double fork, etc.
1810
 
        daemon()
1811
 
    
 
1865
        
1812
1866
    try:
1813
1867
        with pidfile:
1814
1868
            pid = os.getpid()