/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: 2015-07-01 20:01:26 UTC
  • mto: This revision was merged to the branch mainline in revision 759.
  • Revision ID: teddy@recompile.se-20150701200126-qb3f6c3jcas2f4og
mandos-client: Try to start a plugin to add and remove a local route.

* debian/mandos-client.README.Debian: Add setting of environment
                                      variable MANDOSPLUGINHELPERDIR
                                      to command line testing
                                      mandos-client.
* mandos-client.c (raise_privileges): Moved to top of file.
                  (raise_privileges_permanently): - '' -
                  (lower_privileges): - '' -
                  (lower_privileges_permanently): - '' -
  (add_remove_local_route, add_local_route, remove_local_route): New.
  (start_mandos_communication): Set SOCK_CLOEXEC flag on socket.  Run
                                the above functions to add (and
                                remove) local route, if the conditions
                                indicates it could help.
  (run_network_hooks): Use O_DIRECTORY, O_PATH, and O_CLOEXEC flags
                       when opening network hook directory. Do
                       TEMP_FAILURE_RETRY around opening of /dev/null
                       and network hook executables.  Move redirecting
                       of stdout and stderr to as late as possible
                       before fexecve().
  (main): Use O_DIRECTORY and O_PATH when opening temporary directory.
* plugins.d/mandos-client.xml (ENVIRONMENT): Document usage of the
                                             MANDOSPLUGINHELPERDIR
                                             environment variable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
    except ImportError:
89
89
        SO_BINDTODEVICE = None
90
90
 
91
 
version = "1.6.8"
 
91
if sys.version_info.major == 2:
 
92
    str = unicode
 
93
 
 
94
version = "1.6.9"
92
95
stored_state_file = "clients.pickle"
93
96
 
94
97
logger = logging.getLogger()
272
275
        self.bus = bus
273
276
        self.entry_group_state_changed_match = None
274
277
    
275
 
    def rename(self):
 
278
    def rename(self, remove=True):
276
279
        """Derived from the Avahi example code"""
277
280
        if self.rename_count >= self.max_renames:
278
281
            logger.critical("No suitable Zeroconf service name found"
279
282
                            " after %i retries, exiting.",
280
283
                            self.rename_count)
281
284
            raise AvahiServiceError("Too many renames")
282
 
        self.name = unicode(self.server
283
 
                            .GetAlternativeServiceName(self.name))
 
285
        self.name = str(self.server
 
286
                        .GetAlternativeServiceName(self.name))
 
287
        self.rename_count += 1
284
288
        logger.info("Changing Zeroconf service name to %r ...",
285
289
                    self.name)
286
 
        self.remove()
 
290
        if remove:
 
291
            self.remove()
287
292
        try:
288
293
            self.add()
289
294
        except dbus.exceptions.DBusException as error:
290
 
            logger.critical("D-Bus Exception", exc_info=error)
291
 
            self.cleanup()
292
 
            os._exit(1)
293
 
        self.rename_count += 1
 
295
            if (error.get_dbus_name()
 
296
                == "org.freedesktop.Avahi.CollisionError"):
 
297
                logger.info("Local Zeroconf service name collision.")
 
298
                return self.rename(remove=False)
 
299
            else:
 
300
                logger.critical("D-Bus Exception", exc_info=error)
 
301
                self.cleanup()
 
302
                os._exit(1)
294
303
    
295
304
    def remove(self):
296
305
        """Derived from the Avahi example code"""
334
343
            self.rename()
335
344
        elif state == avahi.ENTRY_GROUP_FAILURE:
336
345
            logger.critical("Avahi: Error in group state changed %s",
337
 
                            unicode(error))
 
346
                            str(error))
338
347
            raise AvahiGroupError("State changed: {!s}"
339
348
                                  .format(error))
340
349
    
388
397
 
389
398
 
390
399
class AvahiServiceToSyslog(AvahiService):
391
 
    def rename(self):
 
400
    def rename(self, *args, **kwargs):
392
401
        """Add the new name to the syslog messages"""
393
 
        ret = AvahiService.rename(self)
 
402
        ret = AvahiService.rename(self, *args, **kwargs)
394
403
        syslogger.setFormatter(logging.Formatter
395
404
                               ('Mandos ({}) [%(process)d]:'
396
405
                                ' %(levelname)s: %(message)s'
685
694
        if self.checker is None:
686
695
            # Escape attributes for the shell
687
696
            escaped_attrs = { attr:
688
 
                                  re.escape(unicode(getattr(self,
689
 
                                                            attr)))
 
697
                                  re.escape(str(getattr(self, attr)))
690
698
                              for attr in self.runtime_expansions }
691
699
            try:
692
700
                command = self.checker_command % escaped_attrs
811
819
    """Decorator to annotate D-Bus methods, signals or properties
812
820
    Usage:
813
821
    
 
822
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true",
 
823
                       "org.freedesktop.DBus.Property."
 
824
                       "EmitsChangedSignal": "false"})
814
825
    @dbus_service_property("org.example.Interface", signature="b",
815
826
                           access="r")
816
 
    @dbus_annotations({{"org.freedesktop.DBus.Deprecated": "true",
817
 
                        "org.freedesktop.DBus.Property."
818
 
                        "EmitsChangedSignal": "false"})
819
827
    def Property_dbus_property(self):
820
828
        return dbus.Boolean(False)
821
829
    """
944
952
                                           value.variant_level+1)
945
953
        return dbus.Dictionary(properties, signature="sv")
946
954
    
 
955
    @dbus.service.signal(dbus.PROPERTIES_IFACE, signature="sa{sv}as")
 
956
    def PropertiesChanged(self, interface_name, changed_properties,
 
957
                          invalidated_properties):
 
958
        """Standard D-Bus PropertiesChanged() signal, see D-Bus
 
959
        standard.
 
960
        """
 
961
        pass
 
962
    
947
963
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
948
964
                         out_signature="s",
949
965
                         path_keyword='object_path',
1216
1232
    runtime_expansions = (Client.runtime_expansions
1217
1233
                          + ("dbus_object_path",))
1218
1234
    
 
1235
    _interface = "se.recompile.Mandos.Client"
 
1236
    
1219
1237
    # dbus.service.Object doesn't use super(), so we can't either.
1220
1238
    
1221
1239
    def __init__(self, bus = None, *args, **kwargs):
1223
1241
        Client.__init__(self, *args, **kwargs)
1224
1242
        # Only now, when this client is initialized, can it show up on
1225
1243
        # the D-Bus
1226
 
        client_object_name = unicode(self.name).translate(
 
1244
        client_object_name = str(self.name).translate(
1227
1245
            {ord("."): ord("_"),
1228
1246
             ord("-"): ord("_")})
1229
1247
        self.dbus_object_path = (dbus.ObjectPath
1233
1251
    
1234
1252
    def notifychangeproperty(transform_func,
1235
1253
                             dbus_name, type_func=lambda x: x,
1236
 
                             variant_level=1):
 
1254
                             variant_level=1, invalidate_only=False,
 
1255
                             _interface=_interface):
1237
1256
        """ Modify a variable so that it's a property which announces
1238
1257
        its changes to DBus.
1239
1258
        
1250
1269
                if (not hasattr(self, attrname) or
1251
1270
                    type_func(getattr(self, attrname, None))
1252
1271
                    != type_func(value)):
1253
 
                    dbus_value = transform_func(type_func(value),
1254
 
                                                variant_level
1255
 
                                                =variant_level)
1256
 
                    self.PropertyChanged(dbus.String(dbus_name),
1257
 
                                         dbus_value)
 
1272
                    if invalidate_only:
 
1273
                        self.PropertiesChanged(_interface,
 
1274
                                               dbus.Dictionary(),
 
1275
                                               dbus.Array
 
1276
                                               ((dbus_name,)))
 
1277
                    else:
 
1278
                        dbus_value = transform_func(type_func(value),
 
1279
                                                    variant_level
 
1280
                                                    =variant_level)
 
1281
                        self.PropertyChanged(dbus.String(dbus_name),
 
1282
                                             dbus_value)
 
1283
                        self.PropertiesChanged(_interface,
 
1284
                                               dbus.Dictionary({
 
1285
                                    dbus.String(dbus_name):
 
1286
                                        dbus_value }), dbus.Array())
1258
1287
            setattr(self, attrname, value)
1259
1288
        
1260
1289
        return property(lambda self: getattr(self, attrname), setter)
1298
1327
                                    lambda td: td.total_seconds()
1299
1328
                                    * 1000)
1300
1329
    checker_command = notifychangeproperty(dbus.String, "Checker")
 
1330
    secret = notifychangeproperty(dbus.ByteArray, "Secret",
 
1331
                                  invalidate_only=True)
1301
1332
    
1302
1333
    del notifychangeproperty
1303
1334
    
1350
1381
        self.send_changedstate()
1351
1382
    
1352
1383
    ## D-Bus methods, signals & properties
1353
 
    _interface = "se.recompile.Mandos.Client"
1354
1384
    
1355
1385
    ## Interfaces
1356
1386
    
1357
 
    @dbus_interface_annotations(_interface)
1358
 
    def _foo(self):
1359
 
        return { "org.freedesktop.DBus.Property.EmitsChangedSignal":
1360
 
                     "false"}
1361
 
    
1362
1387
    ## Signals
1363
1388
    
1364
1389
    # CheckerCompleted - signal
1374
1399
        pass
1375
1400
    
1376
1401
    # PropertyChanged - signal
 
1402
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1377
1403
    @dbus.service.signal(_interface, signature="sv")
1378
1404
    def PropertyChanged(self, property, value):
1379
1405
        "D-Bus signal"
1484
1510
    def Host_dbus_property(self, value=None):
1485
1511
        if value is None:       # get
1486
1512
            return dbus.String(self.host)
1487
 
        self.host = unicode(value)
 
1513
        self.host = str(value)
1488
1514
    
1489
1515
    # Created - property
1490
1516
    @dbus_service_property(_interface, signature="s", access="read")
1588
1614
    def Checker_dbus_property(self, value=None):
1589
1615
        if value is None:       # get
1590
1616
            return dbus.String(self.checker_command)
1591
 
        self.checker_command = unicode(value)
 
1617
        self.checker_command = str(value)
1592
1618
    
1593
1619
    # CheckerRunning - property
1594
1620
    @dbus_service_property(_interface, signature="b",
1650
1676
    def handle(self):
1651
1677
        with contextlib.closing(self.server.child_pipe) as child_pipe:
1652
1678
            logger.info("TCP connection from: %s",
1653
 
                        unicode(self.client_address))
 
1679
                        str(self.client_address))
1654
1680
            logger.debug("Pipe FD: %d",
1655
1681
                         self.server.child_pipe.fileno())
1656
1682
            
2707
2733
            def GetAllClientsWithProperties(self):
2708
2734
                "D-Bus method"
2709
2735
                return dbus.Dictionary(
2710
 
                    ((c.dbus_object_path, c.GetAll(""))
2711
 
                     for c in tcp_server.clients.itervalues()),
 
2736
                    { c.dbus_object_path: c.GetAll("")
 
2737
                      for c in tcp_server.clients.itervalues() },
2712
2738
                    signature="oa{sv}")
2713
2739
            
2714
2740
            @dbus.service.method(_interface, in_signature="o")