/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

  • Committer: Teddy Hogeborn
  • Date: 2016-02-28 14:22:10 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 331.
  • Revision ID: teddy@recompile.se-20160228142210-2df89dih7mzxxr0h
Update copyright year.

* DBUS-API: Update copyright year.
* debian/copyright: - '' -
* intro.xml (COPYRIGHT): - '' -
* mandos: - '' -
* mandos-clients.conf.xml (COPYRIGHT): - '' -
* mandos-ctl: - '' -
* mandos-ctl.xml (COPYRIGHT): - '' -
* mandos-keygen: - '' -
* mandos-keygen.xml (COPYRIGHT): - '' -
* mandos-monitor: - '' -
* mandos-monitor.xml (COPYRIGHT): - '' -
* mandos.conf.xml (COPYRIGHT): - '' -
* mandos.xml (COPYRIGHT): - '' -
* plugin-helpers/mandos-client-iprouteadddel.c: - '' -
* plugin-runner.c: - '' -
* plugin-runner.xml (COPYRIGHT): - '' -
* plugins.d/askpass-fifo.c: - '' -
* plugins.d/askpass-fifo.xml (COPYRIGHT): - '' -
* plugins.d/mandos-client.c: - '' -
* plugins.d/mandos-client.xml (COPYRIGHT): - '' -
* plugins.d/password-prompt.c: - '' -
* plugins.d/password-prompt.xml (COPYRIGHT): - ''
* plugins.d/plymouth.c: - '' -
* plugins.d/plymouth.xml (COPYRIGHT): - '' -
* plugins.d/splashy.c: - '' -
* plugins.d/splashy.xml (COPYRIGHT): - '' -
* plugins.d/usplash.c: - '' -
* plugins.d/usplash.xml (COPYRIGHT): - '' -

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
from __future__ import (division, absolute_import, print_function,
35
35
                        unicode_literals)
36
36
 
37
 
try:
38
 
    from future_builtins import *
39
 
except ImportError:
40
 
    pass
 
37
from future_builtins import *
41
38
 
42
39
try:
43
40
    import SocketServer as socketserver
80
77
import dbus
81
78
import dbus.service
82
79
try:
83
 
    from gi.repository import GObject
 
80
    import gobject
84
81
except ImportError:
85
 
    import gobject as GObject
 
82
    from gi.repository import GObject as gobject
 
83
import avahi
86
84
from dbus.mainloop.glib import DBusGMainLoop
87
85
import ctypes
88
86
import ctypes.util
100
98
if sys.version_info.major == 2:
101
99
    str = unicode
102
100
 
103
 
version = "1.7.5"
 
101
version = "1.7.1"
104
102
stored_state_file = "clients.pickle"
105
103
 
106
104
logger = logging.getLogger()
121
119
        return interface_index
122
120
 
123
121
 
124
 
def copy_function(func):
125
 
    """Make a copy of a function"""
126
 
    if sys.version_info.major == 2:
127
 
        return types.FunctionType(func.func_code,
128
 
                                  func.func_globals,
129
 
                                  func.func_name,
130
 
                                  func.func_defaults,
131
 
                                  func.func_closure)
132
 
    else:
133
 
        return types.FunctionType(func.__code__,
134
 
                                  func.__globals__,
135
 
                                  func.__name__,
136
 
                                  func.__defaults__,
137
 
                                  func.__closure__)
138
 
 
139
 
 
140
122
def initlogger(debug, level=logging.WARNING):
141
123
    """init logger and add loglevel"""
142
124
    
173
155
        try:
174
156
            output = subprocess.check_output(["gpgconf"])
175
157
            for line in output.splitlines():
176
 
                name, text, path = line.split(b":")
 
158
                name, text, path = line.split(":")
177
159
                if name == "gpg":
178
160
                    self.gpg = path
179
161
                    break
256
238
            raise PGPError(err)
257
239
        return decrypted_plaintext
258
240
 
259
 
# Pretend that we have an Avahi module
260
 
class Avahi(object):
261
 
    """This isn't so much a class as it is a module-like namespace.
262
 
    It is instantiated once, and simulates having an Avahi module."""
263
 
    IF_UNSPEC = -1              # avahi-common/address.h
264
 
    PROTO_UNSPEC = -1           # avahi-common/address.h
265
 
    PROTO_INET = 0              # avahi-common/address.h
266
 
    PROTO_INET6 = 1             # avahi-common/address.h
267
 
    DBUS_NAME = "org.freedesktop.Avahi"
268
 
    DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
269
 
    DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
270
 
    DBUS_PATH_SERVER = "/"
271
 
    def string_array_to_txt_array(self, t):
272
 
        return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
273
 
                           for s in t), signature="ay")
274
 
    ENTRY_GROUP_ESTABLISHED = 2 # avahi-common/defs.h
275
 
    ENTRY_GROUP_COLLISION = 3   # avahi-common/defs.h
276
 
    ENTRY_GROUP_FAILURE = 4     # avahi-common/defs.h
277
 
    SERVER_INVALID = 0          # avahi-common/defs.h
278
 
    SERVER_REGISTERING = 1      # avahi-common/defs.h
279
 
    SERVER_RUNNING = 2          # avahi-common/defs.h
280
 
    SERVER_COLLISION = 3        # avahi-common/defs.h
281
 
    SERVER_FAILURE = 4          # avahi-common/defs.h
282
 
avahi = Avahi()
283
241
 
284
242
class AvahiError(Exception):
285
243
    def __init__(self, value, *args, **kwargs):
489
447
    
490
448
    _library = ctypes.cdll.LoadLibrary(
491
449
        ctypes.util.find_library("gnutls"))
492
 
    _need_version = b"3.3.0"
 
450
    _need_version = "3.3.0"
493
451
    def __init__(self):
494
452
        # Need to use class name "GnuTLS" here, since this method is
495
453
        # called before the assignment to the "gnutls" global variable
529
487
    openpgp_crt_t = ctypes.POINTER(openpgp_crt_int)
530
488
    openpgp_crt_fmt_t = ctypes.c_int # gnutls/openpgp.h
531
489
    log_func = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
532
 
    credentials_type_t = ctypes.c_int
 
490
    credentials_type_t = ctypes.c_int # 
533
491
    transport_ptr_t = ctypes.c_void_p
534
492
    close_request_t = ctypes.c_int
535
493
    
757
715
    checker:    subprocess.Popen(); a running checker process used
758
716
                                    to see if the client lives.
759
717
                                    'None' if no process is running.
760
 
    checker_callback_tag: a GObject event source tag, or None
 
718
    checker_callback_tag: a gobject event source tag, or None
761
719
    checker_command: string; External command which is run to check
762
720
                     if client lives.  %() expansions are done at
763
721
                     runtime with vars(self) as dict, so that for
764
722
                     instance %(name)s can be used in the command.
765
 
    checker_initiator_tag: a GObject event source tag, or None
 
723
    checker_initiator_tag: a gobject event source tag, or None
766
724
    created:    datetime.datetime(); (UTC) object creation
767
725
    client_structure: Object describing what attributes a client has
768
726
                      and is used for storing the client at exit
769
727
    current_checker_command: string; current running checker_command
770
 
    disable_initiator_tag: a GObject event source tag, or None
 
728
    disable_initiator_tag: a gobject event source tag, or None
771
729
    enabled:    bool()
772
730
    fingerprint: string (40 or 32 hexadecimal digits); used to
773
731
                 uniquely identify the client
836
794
            client["fingerprint"] = (section["fingerprint"].upper()
837
795
                                     .replace(" ", ""))
838
796
            if "secret" in section:
839
 
                client["secret"] = codecs.decode(section["secret"]
840
 
                                                 .encode("utf-8"),
841
 
                                                 "base64")
 
797
                client["secret"] = section["secret"].decode("base64")
842
798
            elif "secfile" in section:
843
799
                with open(os.path.expanduser(os.path.expandvars
844
800
                                             (section["secfile"])),
897
853
        self.changedstate = multiprocessing_manager.Condition(
898
854
            multiprocessing_manager.Lock())
899
855
        self.client_structure = [attr
900
 
                                 for attr in self.__dict__.keys()
 
856
                                 for attr in self.__dict__.iterkeys()
901
857
                                 if not attr.startswith("_")]
902
858
        self.client_structure.append("client_structure")
903
859
        
929
885
        if not quiet:
930
886
            logger.info("Disabling client %s", self.name)
931
887
        if getattr(self, "disable_initiator_tag", None) is not None:
932
 
            GObject.source_remove(self.disable_initiator_tag)
 
888
            gobject.source_remove(self.disable_initiator_tag)
933
889
            self.disable_initiator_tag = None
934
890
        self.expires = None
935
891
        if getattr(self, "checker_initiator_tag", None) is not None:
936
 
            GObject.source_remove(self.checker_initiator_tag)
 
892
            gobject.source_remove(self.checker_initiator_tag)
937
893
            self.checker_initiator_tag = None
938
894
        self.stop_checker()
939
895
        self.enabled = False
940
896
        if not quiet:
941
897
            self.send_changedstate()
942
 
        # Do not run this again if called by a GObject.timeout_add
 
898
        # Do not run this again if called by a gobject.timeout_add
943
899
        return False
944
900
    
945
901
    def __del__(self):
949
905
        # Schedule a new checker to be started an 'interval' from now,
950
906
        # and every interval from then on.
951
907
        if self.checker_initiator_tag is not None:
952
 
            GObject.source_remove(self.checker_initiator_tag)
953
 
        self.checker_initiator_tag = GObject.timeout_add(
 
908
            gobject.source_remove(self.checker_initiator_tag)
 
909
        self.checker_initiator_tag = gobject.timeout_add(
954
910
            int(self.interval.total_seconds() * 1000),
955
911
            self.start_checker)
956
912
        # Schedule a disable() when 'timeout' has passed
957
913
        if self.disable_initiator_tag is not None:
958
 
            GObject.source_remove(self.disable_initiator_tag)
959
 
        self.disable_initiator_tag = GObject.timeout_add(
 
914
            gobject.source_remove(self.disable_initiator_tag)
 
915
        self.disable_initiator_tag = gobject.timeout_add(
960
916
            int(self.timeout.total_seconds() * 1000), self.disable)
961
917
        # Also start a new checker *right now*.
962
918
        self.start_checker()
998
954
        if timeout is None:
999
955
            timeout = self.timeout
1000
956
        if self.disable_initiator_tag is not None:
1001
 
            GObject.source_remove(self.disable_initiator_tag)
 
957
            gobject.source_remove(self.disable_initiator_tag)
1002
958
            self.disable_initiator_tag = None
1003
959
        if getattr(self, "enabled", False):
1004
 
            self.disable_initiator_tag = GObject.timeout_add(
 
960
            self.disable_initiator_tag = gobject.timeout_add(
1005
961
                int(timeout.total_seconds() * 1000), self.disable)
1006
962
            self.expires = datetime.datetime.utcnow() + timeout
1007
963
    
1062
1018
                args = (pipe[1], subprocess.call, command),
1063
1019
                kwargs = popen_args)
1064
1020
            self.checker.start()
1065
 
            self.checker_callback_tag = GObject.io_add_watch(
1066
 
                pipe[0].fileno(), GObject.IO_IN,
 
1021
            self.checker_callback_tag = gobject.io_add_watch(
 
1022
                pipe[0].fileno(), gobject.IO_IN,
1067
1023
                self.checker_callback, pipe[0], command)
1068
 
        # Re-run this periodically if run by GObject.timeout_add
 
1024
        # Re-run this periodically if run by gobject.timeout_add
1069
1025
        return True
1070
1026
    
1071
1027
    def stop_checker(self):
1072
1028
        """Force the checker process, if any, to stop."""
1073
1029
        if self.checker_callback_tag:
1074
 
            GObject.source_remove(self.checker_callback_tag)
 
1030
            gobject.source_remove(self.checker_callback_tag)
1075
1031
            self.checker_callback_tag = None
1076
1032
        if getattr(self, "checker", None) is None:
1077
1033
            return
1551
1507
                interface_names.add(alt_interface)
1552
1508
                # Is this a D-Bus signal?
1553
1509
                if getattr(attribute, "_dbus_is_signal", False):
1554
 
                    # Extract the original non-method undecorated
1555
 
                    # function by black magic
1556
1510
                    if sys.version_info.major == 2:
 
1511
                        # Extract the original non-method undecorated
 
1512
                        # function by black magic
1557
1513
                        nonmethod_func = (dict(
1558
1514
                            zip(attribute.func_code.co_freevars,
1559
1515
                                attribute.__closure__))
1560
1516
                                          ["func"].cell_contents)
1561
1517
                    else:
1562
 
                        nonmethod_func = (dict(
1563
 
                            zip(attribute.__code__.co_freevars,
1564
 
                                attribute.__closure__))
1565
 
                                          ["func"].cell_contents)
 
1518
                        nonmethod_func = attribute
1566
1519
                    # Create a new, but exactly alike, function
1567
1520
                    # object, and decorate it to be a new D-Bus signal
1568
1521
                    # with the alternate D-Bus interface name
1569
 
                    new_function = copy_function(nonmethod_func)
 
1522
                    if sys.version_info.major == 2:
 
1523
                        new_function = types.FunctionType(
 
1524
                            nonmethod_func.func_code,
 
1525
                            nonmethod_func.func_globals,
 
1526
                            nonmethod_func.func_name,
 
1527
                            nonmethod_func.func_defaults,
 
1528
                            nonmethod_func.func_closure)
 
1529
                    else:
 
1530
                        new_function = types.FunctionType(
 
1531
                            nonmethod_func.__code__,
 
1532
                            nonmethod_func.__globals__,
 
1533
                            nonmethod_func.__name__,
 
1534
                            nonmethod_func.__defaults__,
 
1535
                            nonmethod_func.__closure__)
1570
1536
                    new_function = (dbus.service.signal(
1571
1537
                        alt_interface,
1572
1538
                        attribute._dbus_signature)(new_function))
1611
1577
                            alt_interface,
1612
1578
                            attribute._dbus_in_signature,
1613
1579
                            attribute._dbus_out_signature)
1614
 
                        (copy_function(attribute)))
 
1580
                        (types.FunctionType(attribute.func_code,
 
1581
                                            attribute.func_globals,
 
1582
                                            attribute.func_name,
 
1583
                                            attribute.func_defaults,
 
1584
                                            attribute.func_closure)))
1615
1585
                    # Copy annotations, if any
1616
1586
                    try:
1617
1587
                        attr[attrname]._dbus_annotations = dict(
1629
1599
                        attribute._dbus_access,
1630
1600
                        attribute._dbus_get_args_options
1631
1601
                        ["byte_arrays"])
1632
 
                                      (copy_function(attribute)))
 
1602
                                      (types.FunctionType(
 
1603
                                          attribute.func_code,
 
1604
                                          attribute.func_globals,
 
1605
                                          attribute.func_name,
 
1606
                                          attribute.func_defaults,
 
1607
                                          attribute.func_closure)))
1633
1608
                    # Copy annotations, if any
1634
1609
                    try:
1635
1610
                        attr[attrname]._dbus_annotations = dict(
1644
1619
                    # to the class.
1645
1620
                    attr[attrname] = (
1646
1621
                        dbus_interface_annotations(alt_interface)
1647
 
                        (copy_function(attribute)))
 
1622
                        (types.FunctionType(attribute.func_code,
 
1623
                                            attribute.func_globals,
 
1624
                                            attribute.func_name,
 
1625
                                            attribute.func_defaults,
 
1626
                                            attribute.func_closure)))
1648
1627
            if deprecate:
1649
1628
                # Deprecate all alternate interfaces
1650
1629
                iname="_AlternateDBusNames_interface_annotation{}"
1663
1642
            if interface_names:
1664
1643
                # Replace the class with a new subclass of it with
1665
1644
                # methods, signals, etc. as created above.
1666
 
                if sys.version_info.major == 2:
1667
 
                    cls = type(b"{}Alternate".format(cls.__name__),
1668
 
                               (cls, ), attr)
1669
 
                else:
1670
 
                    cls = type("{}Alternate".format(cls.__name__),
1671
 
                               (cls, ), attr)
 
1645
                cls = type(b"{}Alternate".format(cls.__name__),
 
1646
                           (cls, ), attr)
1672
1647
        return cls
1673
1648
    
1674
1649
    return wrapper
1832
1807
    
1833
1808
    def approve(self, value=True):
1834
1809
        self.approved = value
1835
 
        GObject.timeout_add(int(self.approval_duration.total_seconds()
 
1810
        gobject.timeout_add(int(self.approval_duration.total_seconds()
1836
1811
                                * 1000), self._reset_approved)
1837
1812
        self.send_changedstate()
1838
1813
    
2049
2024
                if (getattr(self, "disable_initiator_tag", None)
2050
2025
                    is None):
2051
2026
                    return
2052
 
                GObject.source_remove(self.disable_initiator_tag)
2053
 
                self.disable_initiator_tag = GObject.timeout_add(
 
2027
                gobject.source_remove(self.disable_initiator_tag)
 
2028
                self.disable_initiator_tag = gobject.timeout_add(
2054
2029
                    int((self.expires - now).total_seconds() * 1000),
2055
2030
                    self.disable)
2056
2031
    
2076
2051
            return
2077
2052
        if self.enabled:
2078
2053
            # Reschedule checker run
2079
 
            GObject.source_remove(self.checker_initiator_tag)
2080
 
            self.checker_initiator_tag = GObject.timeout_add(
 
2054
            gobject.source_remove(self.checker_initiator_tag)
 
2055
            self.checker_initiator_tag = gobject.timeout_add(
2081
2056
                value, self.start_checker)
2082
2057
            self.start_checker() # Start one now, too
2083
2058
    
2487
2462
        gnutls_priority GnuTLS priority string
2488
2463
        use_dbus:       Boolean; to emit D-Bus signals or not
2489
2464
    
2490
 
    Assumes a GObject.MainLoop event loop.
 
2465
    Assumes a gobject.MainLoop event loop.
2491
2466
    """
2492
2467
    
2493
2468
    def __init__(self, server_address, RequestHandlerClass,
2518
2493
    
2519
2494
    def add_pipe(self, parent_pipe, proc):
2520
2495
        # Call "handle_ipc" for both data and EOF events
2521
 
        GObject.io_add_watch(
 
2496
        gobject.io_add_watch(
2522
2497
            parent_pipe.fileno(),
2523
 
            GObject.IO_IN | GObject.IO_HUP,
 
2498
            gobject.IO_IN | gobject.IO_HUP,
2524
2499
            functools.partial(self.handle_ipc,
2525
2500
                              parent_pipe = parent_pipe,
2526
2501
                              proc = proc))
2530
2505
                   proc = None,
2531
2506
                   client_object=None):
2532
2507
        # error, or the other end of multiprocessing.Pipe has closed
2533
 
        if condition & (GObject.IO_ERR | GObject.IO_HUP):
 
2508
        if condition & (gobject.IO_ERR | gobject.IO_HUP):
2534
2509
            # Wait for other process to exit
2535
2510
            proc.join()
2536
2511
            return False
2543
2518
            fpr = request[1]
2544
2519
            address = request[2]
2545
2520
            
2546
 
            for c in self.clients.values():
 
2521
            for c in self.clients.itervalues():
2547
2522
                if c.fingerprint == fpr:
2548
2523
                    client = c
2549
2524
                    break
2557
2532
                parent_pipe.send(False)
2558
2533
                return False
2559
2534
            
2560
 
            GObject.io_add_watch(
 
2535
            gobject.io_add_watch(
2561
2536
                parent_pipe.fileno(),
2562
 
                GObject.IO_IN | GObject.IO_HUP,
 
2537
                gobject.IO_IN | gobject.IO_HUP,
2563
2538
                functools.partial(self.handle_ipc,
2564
2539
                                  parent_pipe = parent_pipe,
2565
2540
                                  proc = proc,
2947
2922
            logger.error("Could not open file %r", pidfilename,
2948
2923
                         exc_info=e)
2949
2924
    
2950
 
    for name, group in (("_mandos", "_mandos"),
2951
 
                        ("mandos", "mandos"),
2952
 
                        ("nobody", "nogroup")):
 
2925
    for name in ("_mandos", "mandos", "nobody"):
2953
2926
        try:
2954
2927
            uid = pwd.getpwnam(name).pw_uid
2955
 
            gid = pwd.getpwnam(group).pw_gid
 
2928
            gid = pwd.getpwnam(name).pw_gid
2956
2929
            break
2957
2930
        except KeyError:
2958
2931
            continue
2962
2935
    try:
2963
2936
        os.setgid(gid)
2964
2937
        os.setuid(uid)
2965
 
        if debug:
2966
 
            logger.debug("Did setuid/setgid to {}:{}".format(uid,
2967
 
                                                             gid))
2968
2938
    except OSError as error:
2969
 
        logger.warning("Failed to setuid/setgid to {}:{}: {}"
2970
 
                       .format(uid, gid, os.strerror(error.errno)))
2971
2939
        if error.errno != errno.EPERM:
2972
2940
            raise
2973
2941
    
2995
2963
        # Close all input and output, do double fork, etc.
2996
2964
        daemon()
2997
2965
    
2998
 
    # multiprocessing will use threads, so before we use GObject we
2999
 
    # need to inform GObject that threads will be used.
3000
 
    GObject.threads_init()
 
2966
    # multiprocessing will use threads, so before we use gobject we
 
2967
    # need to inform gobject that threads will be used.
 
2968
    gobject.threads_init()
3001
2969
    
3002
2970
    global main_loop
3003
2971
    # From the Avahi example code
3004
2972
    DBusGMainLoop(set_as_default=True)
3005
 
    main_loop = GObject.MainLoop()
 
2973
    main_loop = gobject.MainLoop()
3006
2974
    bus = dbus.SystemBus()
3007
2975
    # End of Avahi example code
3008
2976
    if use_dbus:
3052
3020
    if server_settings["restore"]:
3053
3021
        try:
3054
3022
            with open(stored_state_path, "rb") as stored_state:
3055
 
                if sys.version_info.major == 2:                
3056
 
                    clients_data, old_client_settings = pickle.load(
3057
 
                        stored_state)
3058
 
                else:
3059
 
                    bytes_clients_data, bytes_old_client_settings = (
3060
 
                        pickle.load(stored_state, encoding = "bytes"))
3061
 
                    ### Fix bytes to strings
3062
 
                    ## clients_data
3063
 
                    # .keys()
3064
 
                    clients_data = { (key.decode("utf-8")
3065
 
                                      if isinstance(key, bytes)
3066
 
                                      else key): value
3067
 
                                     for key, value in
3068
 
                                     bytes_clients_data.items() }
3069
 
                    del bytes_clients_data
3070
 
                    for key in clients_data:
3071
 
                        value = { (k.decode("utf-8")
3072
 
                                   if isinstance(k, bytes) else k): v
3073
 
                                  for k, v in
3074
 
                                  clients_data[key].items() }
3075
 
                        clients_data[key] = value
3076
 
                        # .client_structure
3077
 
                        value["client_structure"] = [
3078
 
                            (s.decode("utf-8")
3079
 
                             if isinstance(s, bytes)
3080
 
                             else s) for s in
3081
 
                            value["client_structure"] ]
3082
 
                        # .name & .host
3083
 
                        for k in ("name", "host"):
3084
 
                            if isinstance(value[k], bytes):
3085
 
                                value[k] = value[k].decode("utf-8")
3086
 
                    ## old_client_settings
3087
 
                    # .keys()
3088
 
                    old_client_settings = {
3089
 
                        (key.decode("utf-8")
3090
 
                         if isinstance(key, bytes)
3091
 
                         else key): value
3092
 
                        for key, value in
3093
 
                        bytes_old_client_settings.items() }
3094
 
                    del bytes_old_client_settings
3095
 
                    # .host
3096
 
                    for value in old_client_settings.values():
3097
 
                        if isinstance(value["host"], bytes):
3098
 
                            value["host"] = (value["host"]
3099
 
                                             .decode("utf-8"))
 
3023
                clients_data, old_client_settings = pickle.load(
 
3024
                    stored_state)
3100
3025
            os.remove(stored_state_path)
3101
3026
        except IOError as e:
3102
3027
            if e.errno == errno.ENOENT:
3241
3166
            def GetAllClients(self):
3242
3167
                "D-Bus method"
3243
3168
                return dbus.Array(c.dbus_object_path for c in
3244
 
                                  tcp_server.clients.values())
 
3169
                                  tcp_server.clients.itervalues())
3245
3170
            
3246
3171
            @dbus_annotations({"org.freedesktop.DBus.Deprecated":
3247
3172
                               "true"})
3252
3177
                return dbus.Dictionary(
3253
3178
                    { c.dbus_object_path: c.GetAll(
3254
3179
                        "se.recompile.Mandos.Client")
3255
 
                      for c in tcp_server.clients.values() },
 
3180
                      for c in tcp_server.clients.itervalues() },
3256
3181
                    signature="oa{sv}")
3257
3182
            
3258
3183
            @dbus.service.method(_interface, in_signature="o")
3259
3184
            def RemoveClient(self, object_path):
3260
3185
                "D-Bus method"
3261
 
                for c in tcp_server.clients.values():
 
3186
                for c in tcp_server.clients.itervalues():
3262
3187
                    if c.dbus_object_path == object_path:
3263
3188
                        del tcp_server.clients[c.name]
3264
3189
                        c.remove_from_connection()
3324
3249
        # removed/edited, old secret will thus be unrecovable.
3325
3250
        clients = {}
3326
3251
        with PGPEngine() as pgp:
3327
 
            for client in tcp_server.clients.values():
 
3252
            for client in tcp_server.clients.itervalues():
3328
3253
                key = client_settings[client.name]["secret"]
3329
3254
                client.encrypted_secret = pgp.encrypt(client.secret,
3330
3255
                                                      key)
3354
3279
                    prefix='clients-',
3355
3280
                    dir=os.path.dirname(stored_state_path),
3356
3281
                    delete=False) as stored_state:
3357
 
                pickle.dump((clients, client_settings), stored_state,
3358
 
                            protocol = 2)
 
3282
                pickle.dump((clients, client_settings), stored_state)
3359
3283
                tempname = stored_state.name
3360
3284
            os.rename(tempname, stored_state_path)
3361
3285
        except (IOError, OSError) as e:
3386
3310
    
3387
3311
    atexit.register(cleanup)
3388
3312
    
3389
 
    for client in tcp_server.clients.values():
 
3313
    for client in tcp_server.clients.itervalues():
3390
3314
        if use_dbus:
3391
3315
            # Emit D-Bus signal for adding
3392
3316
            mandos_dbus_service.client_added_signal(client)
3421
3345
                sys.exit(1)
3422
3346
            # End of Avahi example code
3423
3347
        
3424
 
        GObject.io_add_watch(tcp_server.fileno(), GObject.IO_IN,
 
3348
        gobject.io_add_watch(tcp_server.fileno(), gobject.IO_IN,
3425
3349
                             lambda *args, **kwargs:
3426
3350
                             (tcp_server.handle_request
3427
3351
                              (*args[2:], **kwargs) or True))