/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: 2014-12-21 12:56:08 UTC
  • Revision ID: teddy@recompile.se-20141221125608-bmkvujlj39srpwd3
mandos-keygen: Fix some stylistic quoting issues.

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.7"
 
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()
104
107
        SIOCGIFINDEX = 0x8933  # From /usr/include/linux/sockios.h
105
108
        with contextlib.closing(socket.socket()) as s:
106
109
            ifreq = fcntl.ioctl(s, SIOCGIFINDEX,
107
 
                                struct.pack(str("16s16x"),
108
 
                                            interface))
109
 
        interface_index = struct.unpack(str("I"),
110
 
                                        ifreq[16:20])[0]
 
110
                                struct.pack(b"16s16x", interface))
 
111
        interface_index = struct.unpack("I", ifreq[16:20])[0]
111
112
        return interface_index
112
113
 
113
114
 
118
119
    syslogger = (logging.handlers.SysLogHandler
119
120
                 (facility =
120
121
                  logging.handlers.SysLogHandler.LOG_DAEMON,
121
 
                  address = str("/dev/log")))
 
122
                  address = "/dev/log"))
122
123
    syslogger.setFormatter(logging.Formatter
123
124
                           ('Mandos [%(process)d]: %(levelname)s:'
124
125
                            ' %(message)s'))
224
225
class AvahiError(Exception):
225
226
    def __init__(self, value, *args, **kwargs):
226
227
        self.value = value
227
 
        super(AvahiError, self).__init__(value, *args, **kwargs)
228
 
    def __unicode__(self):
229
 
        return unicode(repr(self.value))
 
228
        return super(AvahiError, self).__init__(value, *args,
 
229
                                                **kwargs)
230
230
 
231
231
class AvahiServiceError(AvahiError):
232
232
    pass
275
275
        self.bus = bus
276
276
        self.entry_group_state_changed_match = None
277
277
    
278
 
    def rename(self):
 
278
    def rename(self, remove=True):
279
279
        """Derived from the Avahi example code"""
280
280
        if self.rename_count >= self.max_renames:
281
281
            logger.critical("No suitable Zeroconf service name found"
282
282
                            " after %i retries, exiting.",
283
283
                            self.rename_count)
284
284
            raise AvahiServiceError("Too many renames")
285
 
        self.name = unicode(self.server
286
 
                            .GetAlternativeServiceName(self.name))
 
285
        self.name = str(self.server
 
286
                        .GetAlternativeServiceName(self.name))
 
287
        self.rename_count += 1
287
288
        logger.info("Changing Zeroconf service name to %r ...",
288
289
                    self.name)
289
 
        self.remove()
 
290
        if remove:
 
291
            self.remove()
290
292
        try:
291
293
            self.add()
292
294
        except dbus.exceptions.DBusException as error:
293
 
            logger.critical("D-Bus Exception", exc_info=error)
294
 
            self.cleanup()
295
 
            os._exit(1)
296
 
        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)
297
303
    
298
304
    def remove(self):
299
305
        """Derived from the Avahi example code"""
337
343
            self.rename()
338
344
        elif state == avahi.ENTRY_GROUP_FAILURE:
339
345
            logger.critical("Avahi: Error in group state changed %s",
340
 
                            unicode(error))
 
346
                            str(error))
341
347
            raise AvahiGroupError("State changed: {!s}"
342
348
                                  .format(error))
343
349
    
391
397
 
392
398
 
393
399
class AvahiServiceToSyslog(AvahiService):
394
 
    def rename(self):
 
400
    def rename(self, *args, **kwargs):
395
401
        """Add the new name to the syslog messages"""
396
 
        ret = AvahiService.rename(self)
 
402
        ret = AvahiService.rename(self, *args, **kwargs)
397
403
        syslogger.setFormatter(logging.Formatter
398
404
                               ('Mandos ({}) [%(process)d]:'
399
405
                                ' %(levelname)s: %(message)s'
481
487
            client["enabled"] = config.getboolean(client_name,
482
488
                                                  "enabled")
483
489
            
 
490
            # Uppercase and remove spaces from fingerprint for later
 
491
            # comparison purposes with return value from the
 
492
            # fingerprint() function
484
493
            client["fingerprint"] = (section["fingerprint"].upper()
485
494
                                     .replace(" ", ""))
486
495
            if "secret" in section:
528
537
            self.expires = None
529
538
        
530
539
        logger.debug("Creating client %r", self.name)
531
 
        # Uppercase and remove spaces from fingerprint for later
532
 
        # comparison purposes with return value from the fingerprint()
533
 
        # function
534
540
        logger.debug("  Fingerprint: %s", self.fingerprint)
535
541
        self.created = settings.get("created",
536
542
                                    datetime.datetime.utcnow())
688
694
        if self.checker is None:
689
695
            # Escape attributes for the shell
690
696
            escaped_attrs = { attr:
691
 
                                  re.escape(unicode(getattr(self,
692
 
                                                            attr)))
 
697
                                  re.escape(str(getattr(self, attr)))
693
698
                              for attr in self.runtime_expansions }
694
699
            try:
695
700
                command = self.checker_command % escaped_attrs
814
819
    """Decorator to annotate D-Bus methods, signals or properties
815
820
    Usage:
816
821
    
 
822
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true",
 
823
                       "org.freedesktop.DBus.Property."
 
824
                       "EmitsChangedSignal": "false"})
817
825
    @dbus_service_property("org.example.Interface", signature="b",
818
826
                           access="r")
819
 
    @dbus_annotations({{"org.freedesktop.DBus.Deprecated": "true",
820
 
                        "org.freedesktop.DBus.Property."
821
 
                        "EmitsChangedSignal": "false"})
822
827
    def Property_dbus_property(self):
823
828
        return dbus.Boolean(False)
824
829
    """
831
836
class DBusPropertyException(dbus.exceptions.DBusException):
832
837
    """A base class for D-Bus property-related exceptions
833
838
    """
834
 
    def __unicode__(self):
835
 
        return unicode(str(self))
836
 
 
 
839
    pass
837
840
 
838
841
class DBusPropertyAccessException(DBusPropertyException):
839
842
    """A property's access permissions disallows an operation.
949
952
                                           value.variant_level+1)
950
953
        return dbus.Dictionary(properties, signature="sv")
951
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
    
952
963
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
953
964
                         out_signature="s",
954
965
                         path_keyword='object_path',
1221
1232
    runtime_expansions = (Client.runtime_expansions
1222
1233
                          + ("dbus_object_path",))
1223
1234
    
 
1235
    _interface = "se.recompile.Mandos.Client"
 
1236
    
1224
1237
    # dbus.service.Object doesn't use super(), so we can't either.
1225
1238
    
1226
1239
    def __init__(self, bus = None, *args, **kwargs):
1228
1241
        Client.__init__(self, *args, **kwargs)
1229
1242
        # Only now, when this client is initialized, can it show up on
1230
1243
        # the D-Bus
1231
 
        client_object_name = unicode(self.name).translate(
 
1244
        client_object_name = str(self.name).translate(
1232
1245
            {ord("."): ord("_"),
1233
1246
             ord("-"): ord("_")})
1234
1247
        self.dbus_object_path = (dbus.ObjectPath
1238
1251
    
1239
1252
    def notifychangeproperty(transform_func,
1240
1253
                             dbus_name, type_func=lambda x: x,
1241
 
                             variant_level=1):
 
1254
                             variant_level=1, invalidate_only=False,
 
1255
                             _interface=_interface):
1242
1256
        """ Modify a variable so that it's a property which announces
1243
1257
        its changes to DBus.
1244
1258
        
1255
1269
                if (not hasattr(self, attrname) or
1256
1270
                    type_func(getattr(self, attrname, None))
1257
1271
                    != type_func(value)):
1258
 
                    dbus_value = transform_func(type_func(value),
1259
 
                                                variant_level
1260
 
                                                =variant_level)
1261
 
                    self.PropertyChanged(dbus.String(dbus_name),
1262
 
                                         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())
1263
1287
            setattr(self, attrname, value)
1264
1288
        
1265
1289
        return property(lambda self: getattr(self, attrname), setter)
1303
1327
                                    lambda td: td.total_seconds()
1304
1328
                                    * 1000)
1305
1329
    checker_command = notifychangeproperty(dbus.String, "Checker")
 
1330
    secret = notifychangeproperty(dbus.ByteArray, "Secret",
 
1331
                                  invalidate_only=True)
1306
1332
    
1307
1333
    del notifychangeproperty
1308
1334
    
1355
1381
        self.send_changedstate()
1356
1382
    
1357
1383
    ## D-Bus methods, signals & properties
1358
 
    _interface = "se.recompile.Mandos.Client"
1359
1384
    
1360
1385
    ## Interfaces
1361
1386
    
1362
 
    @dbus_interface_annotations(_interface)
1363
 
    def _foo(self):
1364
 
        return { "org.freedesktop.DBus.Property.EmitsChangedSignal":
1365
 
                     "false"}
1366
 
    
1367
1387
    ## Signals
1368
1388
    
1369
1389
    # CheckerCompleted - signal
1379
1399
        pass
1380
1400
    
1381
1401
    # PropertyChanged - signal
 
1402
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1382
1403
    @dbus.service.signal(_interface, signature="sv")
1383
1404
    def PropertyChanged(self, property, value):
1384
1405
        "D-Bus signal"
1489
1510
    def Host_dbus_property(self, value=None):
1490
1511
        if value is None:       # get
1491
1512
            return dbus.String(self.host)
1492
 
        self.host = unicode(value)
 
1513
        self.host = str(value)
1493
1514
    
1494
1515
    # Created - property
1495
1516
    @dbus_service_property(_interface, signature="s", access="read")
1593
1614
    def Checker_dbus_property(self, value=None):
1594
1615
        if value is None:       # get
1595
1616
            return dbus.String(self.checker_command)
1596
 
        self.checker_command = unicode(value)
 
1617
        self.checker_command = str(value)
1597
1618
    
1598
1619
    # CheckerRunning - property
1599
1620
    @dbus_service_property(_interface, signature="b",
1615
1636
    @dbus_service_property(_interface, signature="ay",
1616
1637
                           access="write", byte_arrays=True)
1617
1638
    def Secret_dbus_property(self, value):
1618
 
        self.secret = str(value)
 
1639
        self.secret = bytes(value)
1619
1640
    
1620
1641
    del _interface
1621
1642
 
1655
1676
    def handle(self):
1656
1677
        with contextlib.closing(self.server.child_pipe) as child_pipe:
1657
1678
            logger.info("TCP connection from: %s",
1658
 
                        unicode(self.client_address))
 
1679
                        str(self.client_address))
1659
1680
            logger.debug("Pipe FD: %d",
1660
1681
                         self.server.child_pipe.fileno())
1661
1682
            
1960
1981
                try:
1961
1982
                    self.socket.setsockopt(socket.SOL_SOCKET,
1962
1983
                                           SO_BINDTODEVICE,
1963
 
                                           str(self.interface + '\0'))
 
1984
                                           (self.interface + "\0")
 
1985
                                           .encode("utf-8"))
1964
1986
                except socket.error as error:
1965
1987
                    if error.errno == errno.EPERM:
1966
1988
                        logger.error("No permission to bind to"
2226
2248
    timevalue = datetime.timedelta(0)
2227
2249
    for s in interval.split():
2228
2250
        try:
2229
 
            suffix = unicode(s[-1])
 
2251
            suffix = s[-1]
2230
2252
            value = int(s[:-1])
2231
2253
            if suffix == "d":
2232
2254
                delta = datetime.timedelta(value)
2383
2405
    del options
2384
2406
    # Force all strings to be unicode
2385
2407
    for option in server_settings.keys():
2386
 
        if type(server_settings[option]) is str:
2387
 
            server_settings[option] = unicode(server_settings[option])
 
2408
        if isinstance(server_settings[option], bytes):
 
2409
            server_settings[option] = (server_settings[option]
 
2410
                                       .decode("utf-8"))
2388
2411
    # Force all boolean options to be boolean
2389
2412
    for option in ("debug", "use_dbus", "use_ipv6", "restore",
2390
2413
                   "foreground", "zeroconf"):
2533
2556
                                       protocol = protocol, bus = bus)
2534
2557
        if server_settings["interface"]:
2535
2558
            service.interface = (if_nametoindex
2536
 
                                 (str(server_settings["interface"])))
 
2559
                                 (server_settings["interface"]
 
2560
                                  .encode("utf-8")))
2537
2561
    
2538
2562
    global multiprocessing_manager
2539
2563
    multiprocessing_manager = multiprocessing.Manager()
2657
2681
            try:
2658
2682
                with pidfile:
2659
2683
                    pid = os.getpid()
2660
 
                    pidfile.write(str(pid) + "\n".encode("utf-8"))
 
2684
                    pidfile.write("{}\n".format(pid).encode("utf-8"))
2661
2685
            except IOError:
2662
2686
                logger.error("Could not write to file %r with PID %d",
2663
2687
                             pidfilename, pid)
2709
2733
            def GetAllClientsWithProperties(self):
2710
2734
                "D-Bus method"
2711
2735
                return dbus.Dictionary(
2712
 
                    ((c.dbus_object_path, c.GetAll(""))
2713
 
                     for c in tcp_server.clients.itervalues()),
 
2736
                    { c.dbus_object_path: c.GetAll("")
 
2737
                      for c in tcp_server.clients.itervalues() },
2714
2738
                    signature="oa{sv}")
2715
2739
            
2716
2740
            @dbus.service.method(_interface, in_signature="o")