/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: 2010-09-12 03:00:40 UTC
  • Revision ID: teddy@fukt.bsnet.se-20100912030040-b0uopyennste9fdh
Documentation changes:

* DBUS-API: New file documenting the server D-Bus interface.

* clients.conf: Add examples of new approval settings.

* debian/mandos.docs: Added "DBUS-API".

* mandos-clients.conf.xml (OPTIONS): Added "approved_by_default",
                                     "approval_delay", and
                                     "approval_duration".
* mandos.xml (D-BUS INTERFACE): Refer to the "DBUS-API" file.
  (BUGS): Remove mention of lack of a remote query interface.

Show diffs side-by-side

added added

removed removed

Lines of Context:
165
165
                                u' %%(levelname)s: %%(message)s'
166
166
                                % self.name))
167
167
        self.remove()
168
 
        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)
169
174
        self.rename_count += 1
170
175
    def remove(self):
171
176
        """Derived from the Avahi example code"""
194
199
        self.group.Commit()
195
200
    def entry_group_state_changed(self, state, error):
196
201
        """Derived from the Avahi example code"""
197
 
        logger.debug(u"Avahi state change: %i", state)
 
202
        logger.debug(u"Avahi entry group state change: %i", state)
198
203
        
199
204
        if state == avahi.ENTRY_GROUP_ESTABLISHED:
200
205
            logger.debug(u"Zeroconf service established.")
213
218
            self.group = None
214
219
    def server_state_changed(self, state):
215
220
        """Derived from the Avahi example code"""
 
221
        logger.debug(u"Avahi server state change: %i", state)
216
222
        if state == avahi.SERVER_COLLISION:
217
223
            logger.error(u"Zeroconf server name collision")
218
224
            self.remove()
259
265
                     runtime with vars(self) as dict, so that for
260
266
                     instance %(name)s can be used in the command.
261
267
    current_checker_command: string; current running checker_command
262
 
    approved_delay: datetime.timedelta(); Time to wait for approval
 
268
    approval_delay: datetime.timedelta(); Time to wait for approval
263
269
    _approved:   bool(); 'None' if not yet approved/disapproved
264
 
    approved_duration: datetime.timedelta(); Duration of one approval
 
270
    approval_duration: datetime.timedelta(); Duration of one approval
265
271
    """
266
272
    
267
273
    @staticmethod
279
285
        "Return the 'interval' attribute in milliseconds"
280
286
        return self._timedelta_to_milliseconds(self.interval)
281
287
 
282
 
    def approved_delay_milliseconds(self):
283
 
        return self._timedelta_to_milliseconds(self.approved_delay)
 
288
    def approval_delay_milliseconds(self):
 
289
        return self._timedelta_to_milliseconds(self.approval_delay)
284
290
    
285
291
    def __init__(self, name = None, disable_hook=None, config=None):
286
292
        """Note: the 'checker' key in 'config' sets the
325
331
        self.approved_by_default = config.get(u"approved_by_default",
326
332
                                              True)
327
333
        self.approvals_pending = 0
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):
710
716
                                  + self.name.replace(u".", u"_")))
711
717
        DBusObjectWithProperties.__init__(self, self.bus,
712
718
                                          self.dbus_object_path)
713
 
 
 
719
        
714
720
    def _get_approvals_pending(self):
715
721
        return self._approvals_pending
716
722
    def _set_approvals_pending(self, value):
720
726
        if (hasattr(self, "dbus_object_path")
721
727
            and bval is not bool(old_value)):
722
728
            dbus_bool = dbus.Boolean(bval, variant_level=1)
723
 
            self.PropertyChanged(dbus.String(u"approved_pending"),
 
729
            self.PropertyChanged(dbus.String(u"ApprovalPending"),
724
730
                                 dbus_bool)
725
731
 
726
732
    approvals_pending = property(_get_approvals_pending,
738
744
        r = Client.enable(self)
739
745
        if oldstate != self.enabled:
740
746
            # Emit D-Bus signals
741
 
            self.PropertyChanged(dbus.String(u"enabled"),
 
747
            self.PropertyChanged(dbus.String(u"Enabled"),
742
748
                                 dbus.Boolean(True, variant_level=1))
743
749
            self.PropertyChanged(
744
 
                dbus.String(u"last_enabled"),
 
750
                dbus.String(u"LastEnabled"),
745
751
                self._datetime_to_dbus(self.last_enabled,
746
752
                                       variant_level=1))
747
753
        return r
751
757
        r = Client.disable(self, quiet=quiet)
752
758
        if not quiet and oldstate != self.enabled:
753
759
            # Emit D-Bus signal
754
 
            self.PropertyChanged(dbus.String(u"enabled"),
 
760
            self.PropertyChanged(dbus.String(u"Enabled"),
755
761
                                 dbus.Boolean(False, variant_level=1))
756
762
        return r
757
763
    
769
775
        self.checker_callback_tag = None
770
776
        self.checker = None
771
777
        # Emit D-Bus signal
772
 
        self.PropertyChanged(dbus.String(u"checker_running"),
 
778
        self.PropertyChanged(dbus.String(u"CheckerRunning"),
773
779
                             dbus.Boolean(False, variant_level=1))
774
780
        if os.WIFEXITED(condition):
775
781
            exitstatus = os.WEXITSTATUS(condition)
790
796
        r = Client.checked_ok(self, *args, **kwargs)
791
797
        # Emit D-Bus signal
792
798
        self.PropertyChanged(
793
 
            dbus.String(u"last_checked_ok"),
 
799
            dbus.String(u"LastCheckedOK"),
794
800
            (self._datetime_to_dbus(self.last_checked_ok,
795
801
                                    variant_level=1)))
796
802
        return r
808
814
            # Emit D-Bus signal
809
815
            self.CheckerStarted(self.current_checker_command)
810
816
            self.PropertyChanged(
811
 
                dbus.String(u"checker_running"),
 
817
                dbus.String(u"CheckerRunning"),
812
818
                dbus.Boolean(True, variant_level=1))
813
819
        return r
814
820
    
817
823
        r = Client.stop_checker(self, *args, **kwargs)
818
824
        if (old_checker is not None
819
825
            and getattr(self, u"checker", None) is None):
820
 
            self.PropertyChanged(dbus.String(u"checker_running"),
 
826
            self.PropertyChanged(dbus.String(u"CheckerRunning"),
821
827
                                 dbus.Boolean(False, variant_level=1))
822
828
        return r
823
829
 
828
834
    def approve(self, value=True):
829
835
        self.send_changedstate()
830
836
        self._approved = value
831
 
        gobject.timeout_add(self._timedelta_to_milliseconds(self.approved_duration),
 
837
        gobject.timeout_add(self._timedelta_to_milliseconds
 
838
                            (self.approval_duration),
832
839
                            self._reset_approved)
833
840
    
834
841
    
871
878
        pass
872
879
    
873
880
    # NeedApproval - signal
874
 
    @dbus.service.signal(_interface, signature=u"db")
 
881
    @dbus.service.signal(_interface, signature=u"tb")
875
882
    def NeedApproval(self, timeout, default):
876
883
        "D-Bus signal"
877
884
        pass
913
920
    
914
921
    ## Properties
915
922
    
916
 
    # approved_pending - property
 
923
    # ApprovalPending - property
917
924
    @dbus_service_property(_interface, signature=u"b", access=u"read")
918
 
    def approved_pending_dbus_property(self):
 
925
    def ApprovalPending_dbus_property(self):
919
926
        return dbus.Boolean(bool(self.approvals_pending))
920
927
    
921
 
    # approved_by_default - property
 
928
    # ApprovedByDefault - property
922
929
    @dbus_service_property(_interface, signature=u"b",
923
930
                           access=u"readwrite")
924
 
    def approved_by_default_dbus_property(self):
925
 
        return dbus.Boolean(self.approved_by_default)
926
 
    
927
 
    # approved_delay - property
928
 
    @dbus_service_property(_interface, signature=u"t",
929
 
                           access=u"readwrite")
930
 
    def approved_delay_dbus_property(self):
931
 
        return dbus.UInt64(self.approved_delay_milliseconds())
932
 
    
933
 
    # approved_duration - property
934
 
    @dbus_service_property(_interface, signature=u"t",
935
 
                           access=u"readwrite")
936
 
    def approved_duration_dbus_property(self):
937
 
        return dbus.UInt64(self._timedelta_to_milliseconds(
938
 
                self.approved_duration))
939
 
    
940
 
    # 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
941
963
    @dbus_service_property(_interface, signature=u"s", access=u"read")
942
 
    def name_dbus_property(self):
 
964
    def Name_dbus_property(self):
943
965
        return dbus.String(self.name)
944
966
    
945
 
    # fingerprint - property
 
967
    # Fingerprint - property
946
968
    @dbus_service_property(_interface, signature=u"s", access=u"read")
947
 
    def fingerprint_dbus_property(self):
 
969
    def Fingerprint_dbus_property(self):
948
970
        return dbus.String(self.fingerprint)
949
971
    
950
 
    # host - property
 
972
    # Host - property
951
973
    @dbus_service_property(_interface, signature=u"s",
952
974
                           access=u"readwrite")
953
 
    def host_dbus_property(self, value=None):
 
975
    def Host_dbus_property(self, value=None):
954
976
        if value is None:       # get
955
977
            return dbus.String(self.host)
956
978
        self.host = value
957
979
        # Emit D-Bus signal
958
 
        self.PropertyChanged(dbus.String(u"host"),
 
980
        self.PropertyChanged(dbus.String(u"Host"),
959
981
                             dbus.String(value, variant_level=1))
960
982
    
961
 
    # created - property
 
983
    # Created - property
962
984
    @dbus_service_property(_interface, signature=u"s", access=u"read")
963
 
    def created_dbus_property(self):
 
985
    def Created_dbus_property(self):
964
986
        return dbus.String(self._datetime_to_dbus(self.created))
965
987
    
966
 
    # last_enabled - property
 
988
    # LastEnabled - property
967
989
    @dbus_service_property(_interface, signature=u"s", access=u"read")
968
 
    def last_enabled_dbus_property(self):
 
990
    def LastEnabled_dbus_property(self):
969
991
        if self.last_enabled is None:
970
992
            return dbus.String(u"")
971
993
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
972
994
    
973
 
    # enabled - property
 
995
    # Enabled - property
974
996
    @dbus_service_property(_interface, signature=u"b",
975
997
                           access=u"readwrite")
976
 
    def enabled_dbus_property(self, value=None):
 
998
    def Enabled_dbus_property(self, value=None):
977
999
        if value is None:       # get
978
1000
            return dbus.Boolean(self.enabled)
979
1001
        if value:
981
1003
        else:
982
1004
            self.disable()
983
1005
    
984
 
    # last_checked_ok - property
 
1006
    # LastCheckedOK - property
985
1007
    @dbus_service_property(_interface, signature=u"s",
986
1008
                           access=u"readwrite")
987
 
    def last_checked_ok_dbus_property(self, value=None):
 
1009
    def LastCheckedOK_dbus_property(self, value=None):
988
1010
        if value is not None:
989
1011
            self.checked_ok()
990
1012
            return
993
1015
        return dbus.String(self._datetime_to_dbus(self
994
1016
                                                  .last_checked_ok))
995
1017
    
996
 
    # timeout - property
 
1018
    # Timeout - property
997
1019
    @dbus_service_property(_interface, signature=u"t",
998
1020
                           access=u"readwrite")
999
 
    def timeout_dbus_property(self, value=None):
 
1021
    def Timeout_dbus_property(self, value=None):
1000
1022
        if value is None:       # get
1001
1023
            return dbus.UInt64(self.timeout_milliseconds())
1002
1024
        self.timeout = datetime.timedelta(0, 0, 0, value)
1003
1025
        # Emit D-Bus signal
1004
 
        self.PropertyChanged(dbus.String(u"timeout"),
 
1026
        self.PropertyChanged(dbus.String(u"Timeout"),
1005
1027
                             dbus.UInt64(value, variant_level=1))
1006
1028
        if getattr(self, u"disable_initiator_tag", None) is None:
1007
1029
            return
1021
1043
            self.disable_initiator_tag = (gobject.timeout_add
1022
1044
                                          (time_to_die, self.disable))
1023
1045
    
1024
 
    # interval - property
 
1046
    # Interval - property
1025
1047
    @dbus_service_property(_interface, signature=u"t",
1026
1048
                           access=u"readwrite")
1027
 
    def interval_dbus_property(self, value=None):
 
1049
    def Interval_dbus_property(self, value=None):
1028
1050
        if value is None:       # get
1029
1051
            return dbus.UInt64(self.interval_milliseconds())
1030
1052
        self.interval = datetime.timedelta(0, 0, 0, value)
1031
1053
        # Emit D-Bus signal
1032
 
        self.PropertyChanged(dbus.String(u"interval"),
 
1054
        self.PropertyChanged(dbus.String(u"Interval"),
1033
1055
                             dbus.UInt64(value, variant_level=1))
1034
1056
        if getattr(self, u"checker_initiator_tag", None) is None:
1035
1057
            return
1039
1061
                                      (value, self.start_checker))
1040
1062
        self.start_checker()    # Start one now, too
1041
1063
 
1042
 
    # checker - property
 
1064
    # Checker - property
1043
1065
    @dbus_service_property(_interface, signature=u"s",
1044
1066
                           access=u"readwrite")
1045
 
    def checker_dbus_property(self, value=None):
 
1067
    def Checker_dbus_property(self, value=None):
1046
1068
        if value is None:       # get
1047
1069
            return dbus.String(self.checker_command)
1048
1070
        self.checker_command = value
1049
1071
        # Emit D-Bus signal
1050
 
        self.PropertyChanged(dbus.String(u"checker"),
 
1072
        self.PropertyChanged(dbus.String(u"Checker"),
1051
1073
                             dbus.String(self.checker_command,
1052
1074
                                         variant_level=1))
1053
1075
    
1054
 
    # checker_running - property
 
1076
    # CheckerRunning - property
1055
1077
    @dbus_service_property(_interface, signature=u"b",
1056
1078
                           access=u"readwrite")
1057
 
    def checker_running_dbus_property(self, value=None):
 
1079
    def CheckerRunning_dbus_property(self, value=None):
1058
1080
        if value is None:       # get
1059
1081
            return dbus.Boolean(self.checker is not None)
1060
1082
        if value:
1062
1084
        else:
1063
1085
            self.stop_checker()
1064
1086
    
1065
 
    # object_path - property
 
1087
    # ObjectPath - property
1066
1088
    @dbus_service_property(_interface, signature=u"o", access=u"read")
1067
 
    def object_path_dbus_property(self):
 
1089
    def ObjectPath_dbus_property(self):
1068
1090
        return self.dbus_object_path # is already a dbus.ObjectPath
1069
1091
    
1070
 
    # secret = property
 
1092
    # Secret = property
1071
1093
    @dbus_service_property(_interface, signature=u"ay",
1072
1094
                           access=u"write", byte_arrays=True)
1073
 
    def secret_dbus_property(self, value):
 
1095
    def Secret_dbus_property(self, value):
1074
1096
        self.secret = str(value)
1075
1097
    
1076
1098
    del _interface
1174
1196
                except KeyError:
1175
1197
                    return
1176
1198
                
1177
 
                if client.approved_delay:
1178
 
                    delay = client.approved_delay
 
1199
                if client.approval_delay:
 
1200
                    delay = client.approval_delay
1179
1201
                    client.approvals_pending += 1
1180
1202
                    approval_required = True
1181
1203
                
1188
1210
                            client.Rejected("Disabled")                    
1189
1211
                        return
1190
1212
                    
1191
 
                    if client._approved or not client.approved_delay:
 
1213
                    if client._approved or not client.approval_delay:
1192
1214
                        #We are approved or approval is disabled
1193
1215
                        break
1194
1216
                    elif client._approved is None:
1195
 
                        logger.info(u"Client %s need approval",
 
1217
                        logger.info(u"Client %s needs approval",
1196
1218
                                    client.name)
1197
1219
                        if self.server.use_dbus:
1198
1220
                            # Emit D-Bus signal
1199
1221
                            client.NeedApproval(
1200
 
                                client.approved_delay_milliseconds(),
 
1222
                                client.approval_delay_milliseconds(),
1201
1223
                                client.approved_by_default)
1202
1224
                    else:
1203
1225
                        logger.warning(u"Client %s was not approved",
1204
1226
                                       client.name)
1205
1227
                        if self.server.use_dbus:
1206
1228
                            # Emit D-Bus signal
1207
 
                            client.Rejected("Disapproved")
 
1229
                            client.Rejected("Denied")
1208
1230
                        return
1209
1231
                    
1210
1232
                    #wait until timeout or approved
1221
1243
                                           client.name)
1222
1244
                            if self.server.use_dbus:
1223
1245
                                # Emit D-Bus signal
1224
 
                                client.Rejected("Time out")
 
1246
                                client.Rejected("Timed out")
1225
1247
                            return
1226
1248
                        else:
1227
1249
                            break
1253
1275
                try:
1254
1276
                    session.bye()
1255
1277
                except (gnutls.errors.GNUTLSError), error:
1256
 
                    logger.warning("gnutls bye failed")
 
1278
                    logger.warning("GnuTLS bye failed")
1257
1279
    
1258
1280
    @staticmethod
1259
1281
    def peer_certificate(session):
1714
1736
                        u"interval": u"5m",
1715
1737
                        u"checker": u"fping -q -- %%(host)s",
1716
1738
                        u"host": u"",
1717
 
                        u"approved_delay": u"0s",
1718
 
                        u"approved_duration": u"1s",
 
1739
                        u"approval_delay": u"0s",
 
1740
                        u"approval_duration": u"1s",
1719
1741
                        }
1720
1742
    client_config = configparser.SafeConfigParser(client_defaults)
1721
1743
    client_config.read(os.path.join(server_settings[u"configdir"],
1727
1749
    tcp_server = MandosServer((server_settings[u"address"],
1728
1750
                               server_settings[u"port"]),
1729
1751
                              ClientHandler,
1730
 
                              interface=server_settings[u"interface"],
 
1752
                              interface=(server_settings[u"interface"]
 
1753
                                         or None),
1731
1754
                              use_ipv6=use_ipv6,
1732
1755
                              gnutls_priority=
1733
1756
                              server_settings[u"priority"],
1759
1782
        if error[0] != errno.EPERM:
1760
1783
            raise error
1761
1784
    
1762
 
    # Enable all possible GnuTLS debugging
1763
 
 
1764
 
 
1765
1785
    if not debug and not debuglevel:
1766
1786
        syslogger.setLevel(logging.WARNING)
1767
1787
        console.setLevel(logging.WARNING)
1771
1791
        console.setLevel(level)
1772
1792
 
1773
1793
    if debug:
 
1794
        # Enable all possible GnuTLS debugging
 
1795
        
1774
1796
        # "Use a log level over 10 to enable all debugging options."
1775
1797
        # - GnuTLS manual
1776
1798
        gnutls.library.functions.gnutls_global_set_log_level(11)
1781
1803
        
1782
1804
        (gnutls.library.functions
1783
1805
         .gnutls_global_set_log_function(debug_gnutls))
1784
 
 
 
1806
        
1785
1807
        # Redirect stdin so all checkers get /dev/null
1786
1808
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
1787
1809
        os.dup2(null, sys.stdin.fileno())
1790
1812
    else:
1791
1813
        # No console logging
1792
1814
        logger.removeHandler(console)
1793
 
 
 
1815
    
1794
1816
    
1795
1817
    global main_loop
1796
1818
    # From the Avahi example code