/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: 2012-01-08 10:12:18 UTC
  • mfrom: (237.7.101 trunk)
  • Revision ID: teddy@recompile.se-20120108101218-h6yp0akairb23436
merge from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
# "AvahiService" class, and some lines in "main".
12
12
13
13
# Everything else is
14
 
# Copyright © 2008-2011 Teddy Hogeborn
15
 
# Copyright © 2008-2011 Björn Påhlsson
 
14
# Copyright © 2008-2012 Teddy Hogeborn
 
15
# Copyright © 2008-2012 Björn Påhlsson
16
16
17
17
# This program is free software: you can redistribute it and/or modify
18
18
# it under the terms of the GNU General Public License as published by
85
85
    except ImportError:
86
86
        SO_BINDTODEVICE = None
87
87
 
88
 
version = "1.4.1"
 
88
version = "1.5.1"
89
89
stored_state_file = "clients.pickle"
90
90
 
91
91
logger = logging.getLogger()
142
142
        self.gnupg.options.meta_interactive = False
143
143
        self.gnupg.options.homedir = self.tempdir
144
144
        self.gnupg.options.extra_args.extend(['--force-mdc',
145
 
                                              '--quiet'])
 
145
                                              '--quiet',
 
146
                                              '--no-use-agent'])
146
147
    
147
148
    def __enter__(self):
148
149
        return self
421
422
    secret:     bytestring; sent verbatim (over TLS) to client
422
423
    timeout:    datetime.timedelta(); How long from last_checked_ok
423
424
                                      until this client is disabled
424
 
    extended_timeout:   extra long timeout when password has been sent
 
425
    extended_timeout:   extra long timeout when secret has been sent
425
426
    runtime_expansions: Allowed attributes for runtime expansion.
426
427
    expires:    datetime.datetime(); time (UTC) when a client will be
427
428
                disabled, or None
459
460
 
460
461
    @staticmethod
461
462
    def config_parser(config):
462
 
        """ Construct a new dict of client settings of this form:
 
463
        """Construct a new dict of client settings of this form:
463
464
        { client_name: {setting_name: value, ...}, ...}
464
 
        with exceptions for any special settings as defined above"""
 
465
        with exceptions for any special settings as defined above.
 
466
        NOTE: Must be a pure function. Must return the same result
 
467
        value given the same arguments.
 
468
        """
465
469
        settings = {}
466
470
        for client_name in config.sections():
467
471
            section = dict(config.items(client_name))
471
475
            # Reformat values from string types to Python types
472
476
            client["approved_by_default"] = config.getboolean(
473
477
                client_name, "approved_by_default")
474
 
            client["enabled"] = config.getboolean(client_name, "enabled")
 
478
            client["enabled"] = config.getboolean(client_name,
 
479
                                                  "enabled")
475
480
            
476
481
            client["fingerprint"] = (section["fingerprint"].upper()
477
482
                                     .replace(" ", ""))
497
502
            client["last_approval_request"] = None
498
503
            client["last_checked_ok"] = None
499
504
            client["last_checker_status"] = None
500
 
            if client["enabled"]:
501
 
                client["last_enabled"] = datetime.datetime.utcnow()
502
 
                client["expires"] = (datetime.datetime.utcnow()
503
 
                                     + client["timeout"])
504
 
            else:
505
 
                client["last_enabled"] = None
506
 
                client["expires"] = None
507
 
 
 
505
        
508
506
        return settings
509
507
        
510
508
        
517
515
        for setting, value in settings.iteritems():
518
516
            setattr(self, setting, value)
519
517
        
 
518
        if self.enabled:
 
519
            if not hasattr(self, "last_enabled"):
 
520
                self.last_enabled = datetime.datetime.utcnow()
 
521
            if not hasattr(self, "expires"):
 
522
                self.expires = (datetime.datetime.utcnow()
 
523
                                + self.timeout)
 
524
        else:
 
525
            self.last_enabled = None
 
526
            self.expires = None
 
527
       
520
528
        logger.debug("Creating client %r", self.name)
521
529
        # Uppercase and remove spaces from fingerprint for later
522
530
        # comparison purposes with return value from the fingerprint()
523
531
        # function
524
532
        logger.debug("  Fingerprint: %s", self.fingerprint)
525
 
        self.created = settings.get("created", datetime.datetime.utcnow())
 
533
        self.created = settings.get("created",
 
534
                                    datetime.datetime.utcnow())
526
535
 
527
536
        # attributes specific for this server instance
528
537
        self.checker = None
841
850
            # signatures other than "ay".
842
851
            if prop._dbus_signature != "ay":
843
852
                raise ValueError
844
 
            value = dbus.ByteArray(''.join(unichr(byte)
845
 
                                           for byte in value))
 
853
            value = dbus.ByteArray(b''.join(chr(byte)
 
854
                                            for byte in value))
846
855
        prop(value)
847
856
    
848
857
    @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature="s",
1040
1049
    def __init__(self, bus = None, *args, **kwargs):
1041
1050
        self.bus = bus
1042
1051
        Client.__init__(self, *args, **kwargs)
1043
 
        self._approvals_pending = 0
1044
 
        
1045
 
        self._approvals_pending = 0
1046
1052
        # Only now, when this client is initialized, can it show up on
1047
1053
        # the D-Bus
1048
1054
        client_object_name = unicode(self.name).translate(
1218
1224
        "D-Bus signal"
1219
1225
        return self.need_approval()
1220
1226
    
1221
 
    # NeRwequest - signal
1222
 
    @dbus.service.signal(_interface, signature="s")
1223
 
    def NewRequest(self, ip):
1224
 
        """D-Bus signal
1225
 
        Is sent after a client request a password.
1226
 
        """
1227
 
        pass
1228
 
    
1229
1227
    ## Methods
1230
1228
    
1231
1229
    # Approve - method
1358
1356
        if value is None:       # get
1359
1357
            return dbus.UInt64(self.timeout_milliseconds())
1360
1358
        self.timeout = datetime.timedelta(0, 0, 0, value)
1361
 
        if getattr(self, "disable_initiator_tag", None) is None:
1362
 
            return
1363
1359
        # Reschedule timeout
1364
 
        gobject.source_remove(self.disable_initiator_tag)
1365
 
        self.disable_initiator_tag = None
1366
 
        self.expires = None
1367
 
        time_to_die = timedelta_to_milliseconds((self
1368
 
                                                 .last_checked_ok
1369
 
                                                 + self.timeout)
1370
 
                                                - datetime.datetime
1371
 
                                                .utcnow())
1372
 
        if time_to_die <= 0:
1373
 
            # The timeout has passed
1374
 
            self.disable()
1375
 
        else:
1376
 
            self.expires = (datetime.datetime.utcnow()
1377
 
                            + datetime.timedelta(milliseconds =
1378
 
                                                 time_to_die))
1379
 
            self.disable_initiator_tag = (gobject.timeout_add
1380
 
                                          (time_to_die, self.disable))
 
1360
        if self.enabled:
 
1361
            now = datetime.datetime.utcnow()
 
1362
            time_to_die = timedelta_to_milliseconds(
 
1363
                (self.last_checked_ok + self.timeout) - now)
 
1364
            if time_to_die <= 0:
 
1365
                # The timeout has passed
 
1366
                self.disable()
 
1367
            else:
 
1368
                self.expires = (now +
 
1369
                                datetime.timedelta(milliseconds =
 
1370
                                                   time_to_die))
 
1371
                if (getattr(self, "disable_initiator_tag", None)
 
1372
                    is None):
 
1373
                    return
 
1374
                gobject.source_remove(self.disable_initiator_tag)
 
1375
                self.disable_initiator_tag = (gobject.timeout_add
 
1376
                                              (time_to_die,
 
1377
                                               self.disable))
1381
1378
    
1382
1379
    # ExtendedTimeout - property
1383
1380
    @dbus_service_property(_interface, signature="t",
1539
1536
                except KeyError:
1540
1537
                    return
1541
1538
                
1542
 
                if self.server.use_dbus:
1543
 
                    # Emit D-Bus signal
1544
 
                    client.NewRequest(str(self.client_address))
1545
 
                
1546
1539
                if client.approval_delay:
1547
1540
                    delay = client.approval_delay
1548
1541
                    client.approvals_pending += 1
2094
2087
                                % server_settings["servicename"]))
2095
2088
    
2096
2089
    # Parse config file with clients
2097
 
    client_config = configparser.SafeConfigParser(Client.client_defaults)
 
2090
    client_config = configparser.SafeConfigParser(Client
 
2091
                                                  .client_defaults)
2098
2092
    client_config.read(os.path.join(server_settings["configdir"],
2099
2093
                                    "clients.conf"))
2100
2094
    
2241
2235
            
2242
2236
            # Clients who has passed its expire date can still be
2243
2237
            # enabled if its last checker was successful.  Clients
2244
 
            # whose checker failed before we stored its state is
2245
 
            # assumed to have failed all checkers during downtime.
 
2238
            # whose checker succeeded before we stored its state is
 
2239
            # assumed to have successfully run all checkers during
 
2240
            # downtime.
2246
2241
            if client["enabled"]:
2247
2242
                if datetime.datetime.utcnow() >= client["expires"]:
2248
2243
                    if not client["last_checked_ok"]:
2249
2244
                        logger.warning(
2250
2245
                            "disabling client {0} - Client never "
2251
 
                            "performed a successfull checker"
2252
 
                            .format(client["name"]))
 
2246
                            "performed a successful checker"
 
2247
                            .format(client_name))
2253
2248
                        client["enabled"] = False
2254
2249
                    elif client["last_checker_status"] != 0:
2255
2250
                        logger.warning(
2256
2251
                            "disabling client {0} - Client "
2257
2252
                            "last checker failed with error code {1}"
2258
 
                            .format(client["name"],
 
2253
                            .format(client_name,
2259
2254
                                    client["last_checker_status"]))
2260
2255
                        client["enabled"] = False
2261
2256
                    else:
2262
2257
                        client["expires"] = (datetime.datetime
2263
2258
                                             .utcnow()
2264
2259
                                             + client["timeout"])
2265
 
                    
 
2260
                        logger.debug("Last checker succeeded,"
 
2261
                                     " keeping {0} enabled"
 
2262
                                     .format(client_name))
2266
2263
            try:
2267
2264
                client["secret"] = (
2268
2265
                    pgp.decrypt(client["encrypted_secret"],
2277
2274
 
2278
2275
    
2279
2276
    # Add/remove clients based on new changes made to config
2280
 
    for client_name in set(old_client_settings) - set(client_settings):
 
2277
    for client_name in (set(old_client_settings)
 
2278
                        - set(client_settings)):
2281
2279
        del clients_data[client_name]
2282
 
    for client_name in set(client_settings) - set(old_client_settings):
 
2280
    for client_name in (set(client_settings)
 
2281
                        - set(old_client_settings)):
2283
2282
        clients_data[client_name] = client_settings[client_name]
2284
2283
 
2285
 
    # Create clients all clients
 
2284
    # Create all client objects
2286
2285
    for client_name, client in clients_data.iteritems():
2287
2286
        tcp_server.clients[client_name] = client_class(
2288
2287
            name = client_name, settings = client)