/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: 2011-09-26 21:12:40 UTC
  • mfrom: (502.1.1 teddy)
  • Revision ID: teddy@fukt.bsnet.se-20110926211240-qahsqx7nvx5ktjyn
Merge inconsequential change

Show diffs side-by-side

added added

removed removed

Lines of Context:
313
313
                          "created", "enabled", "fingerprint",
314
314
                          "host", "interval", "last_checked_ok",
315
315
                          "last_enabled", "name", "timeout")
316
 
        
 
316
    
317
317
    def timeout_milliseconds(self):
318
318
        "Return the 'timeout' attribute in milliseconds"
319
319
        return _timedelta_to_milliseconds(self.timeout)
320
 
 
 
320
    
321
321
    def extended_timeout_milliseconds(self):
322
322
        "Return the 'extended_timeout' attribute in milliseconds"
323
323
        return _timedelta_to_milliseconds(self.extended_timeout)    
325
325
    def interval_milliseconds(self):
326
326
        "Return the 'interval' attribute in milliseconds"
327
327
        return _timedelta_to_milliseconds(self.interval)
328
 
 
 
328
    
329
329
    def approval_delay_milliseconds(self):
330
330
        return _timedelta_to_milliseconds(self.approval_delay)
331
331
    
509
509
                                       'replace')))
510
510
                    for attr in
511
511
                    self.runtime_expansions)
512
 
 
 
512
                
513
513
                try:
514
514
                    command = self.checker_command % escaped_attrs
515
515
                except TypeError as error:
561
561
                raise
562
562
        self.checker = None
563
563
 
 
564
 
564
565
def dbus_service_property(dbus_interface, signature="v",
565
566
                          access="readwrite", byte_arrays=False):
566
567
    """Decorators for marking methods of a DBusObjectWithProperties to
612
613
 
613
614
class DBusObjectWithProperties(dbus.service.Object):
614
615
    """A D-Bus object with properties.
615
 
 
 
616
    
616
617
    Classes inheriting from this can use the dbus_service_property
617
618
    decorator to expose methods as D-Bus properties.  It exposes the
618
619
    standard Get(), Set(), and GetAll() methods on the D-Bus.
682
683
    def GetAll(self, interface_name):
683
684
        """Standard D-Bus property GetAll() method, see D-Bus
684
685
        standard.
685
 
 
 
686
        
686
687
        Note: Will not include properties with access="write".
687
688
        """
688
689
        all = {}
757
758
    return dbus.String(dt.isoformat(),
758
759
                       variant_level=variant_level)
759
760
 
 
761
 
760
762
class ClientDBus(Client, DBusObjectWithProperties):
761
763
    """A Client class using D-Bus
762
764
    
806
808
                                                variant_level)
807
809
                    self.PropertyChanged(dbus.String(dbus_name),
808
810
                                         dbus_value)
809
 
 
 
811
        
810
812
        return property(lambda self: real_value[0], setter)
811
 
 
812
 
 
 
813
    
 
814
    
813
815
    expires = notifychangeproperty(datetime_to_dbus, "Expires")
814
816
    approvals_pending = notifychangeproperty(dbus.Boolean,
815
817
                                             "ApprovalPending",
867
869
        
868
870
        return Client.checker_callback(self, pid, condition, command,
869
871
                                       *args, **kwargs)
870
 
 
 
872
    
871
873
    def start_checker(self, *args, **kwargs):
872
874
        old_checker = self.checker
873
875
        if self.checker is not None:
1090
1092
                            + datetime.timedelta(milliseconds = time_to_die))
1091
1093
            self.disable_initiator_tag = (gobject.timeout_add
1092
1094
                                          (time_to_die, self.disable))
1093
 
 
 
1095
    
1094
1096
    # ExtendedTimeout - property
1095
1097
    @dbus_service_property(_interface, signature="t",
1096
1098
                           access="readwrite")
1098
1100
        if value is None:       # get
1099
1101
            return dbus.UInt64(self.extended_timeout_milliseconds())
1100
1102
        self.extended_timeout = datetime.timedelta(0, 0, 0, value)
1101
 
 
 
1103
    
1102
1104
    # Interval - property
1103
1105
    @dbus_service_property(_interface, signature="t",
1104
1106
                           access="readwrite")
1113
1115
        self.checker_initiator_tag = (gobject.timeout_add
1114
1116
                                      (value, self.start_checker))
1115
1117
        self.start_checker()    # Start one now, too
1116
 
 
 
1118
    
1117
1119
    # Checker - property
1118
1120
    @dbus_service_property(_interface, signature="s",
1119
1121
                           access="readwrite")
1153
1155
        self._pipe.send(('init', fpr, address))
1154
1156
        if not self._pipe.recv():
1155
1157
            raise KeyError()
1156
 
 
 
1158
    
1157
1159
    def __getattribute__(self, name):
1158
1160
        if(name == '_pipe'):
1159
1161
            return super(ProxyClient, self).__getattribute__(name)
1166
1168
                self._pipe.send(('funcall', name, args, kwargs))
1167
1169
                return self._pipe.recv()[1]
1168
1170
            return func
1169
 
 
 
1171
    
1170
1172
    def __setattr__(self, name, value):
1171
1173
        if(name == '_pipe'):
1172
1174
            return super(ProxyClient, self).__setattr__(name, value)
1185
1187
                        unicode(self.client_address))
1186
1188
            logger.debug("Pipe FD: %d",
1187
1189
                         self.server.child_pipe.fileno())
1188
 
 
 
1190
            
1189
1191
            session = (gnutls.connection
1190
1192
                       .ClientSession(self.request,
1191
1193
                                      gnutls.connection
1192
1194
                                      .X509Credentials()))
1193
 
 
 
1195
            
1194
1196
            # Note: gnutls.connection.X509Credentials is really a
1195
1197
            # generic GnuTLS certificate credentials object so long as
1196
1198
            # no X.509 keys are added to it.  Therefore, we can use it
1197
1199
            # here despite using OpenPGP certificates.
1198
 
 
 
1200
            
1199
1201
            #priority = ':'.join(("NONE", "+VERS-TLS1.1",
1200
1202
            #                      "+AES-256-CBC", "+SHA1",
1201
1203
            #                      "+COMP-NULL", "+CTYPE-OPENPGP",
1207
1209
            (gnutls.library.functions
1208
1210
             .gnutls_priority_set_direct(session._c_object,
1209
1211
                                         priority, None))
1210
 
 
 
1212
            
1211
1213
            # Start communication using the Mandos protocol
1212
1214
            # Get protocol number
1213
1215
            line = self.request.makefile().readline()
1218
1220
            except (ValueError, IndexError, RuntimeError) as error:
1219
1221
                logger.error("Unknown protocol version: %s", error)
1220
1222
                return
1221
 
 
 
1223
            
1222
1224
            # Start GnuTLS connection
1223
1225
            try:
1224
1226
                session.handshake()
1228
1230
                # established.  Just abandon the request.
1229
1231
                return
1230
1232
            logger.debug("Handshake succeeded")
1231
 
 
 
1233
            
1232
1234
            approval_required = False
1233
1235
            try:
1234
1236
                try:
1239
1241
                    logger.warning("Bad certificate: %s", error)
1240
1242
                    return
1241
1243
                logger.debug("Fingerprint: %s", fpr)
1242
 
 
 
1244
                
1243
1245
                try:
1244
1246
                    client = ProxyClient(child_pipe, fpr,
1245
1247
                                         self.client_address)
1311
1313
                                 sent, len(client.secret)
1312
1314
                                 - (sent_size + sent))
1313
1315
                    sent_size += sent
1314
 
 
 
1316
                
1315
1317
                logger.info("Sending secret to %s", client.name)
1316
1318
                # bump the timeout as if seen
1317
1319
                client.checked_ok(client.extended_timeout)
1405
1407
        multiprocessing.Process(target = self.sub_process_main,
1406
1408
                                args = (request, address)).start()
1407
1409
 
 
1410
 
1408
1411
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
1409
1412
    """ adds a pipe to the MixIn """
1410
1413
    def process_request(self, request, client_address):
1413
1416
        This function creates a new pipe in self.pipe
1414
1417
        """
1415
1418
        parent_pipe, self.child_pipe = multiprocessing.Pipe()
1416
 
 
 
1419
        
1417
1420
        super(MultiprocessingMixInWithPipe,
1418
1421
              self).process_request(request, client_address)
1419
1422
        self.child_pipe.close()
1420
1423
        self.add_pipe(parent_pipe)
1421
 
 
 
1424
    
1422
1425
    def add_pipe(self, parent_pipe):
1423
1426
        """Dummy function; override as necessary"""
1424
1427
        raise NotImplementedError
1425
1428
 
 
1429
 
1426
1430
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
1427
1431
                     socketserver.TCPServer, object):
1428
1432
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
1576
1580
            kwargs = request[3]
1577
1581
            
1578
1582
            parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1579
 
 
 
1583
        
1580
1584
        if command == 'getattr':
1581
1585
            attrname = request[1]
1582
1586
            if callable(client_object.__getattribute__(attrname)):
1588
1592
            attrname = request[1]
1589
1593
            value = request[2]
1590
1594
            setattr(client_object, attrname, value)
1591
 
 
 
1595
        
1592
1596
        return True
1593
1597
 
1594
1598
 
1773
1777
    debuglevel = server_settings["debuglevel"]
1774
1778
    use_dbus = server_settings["use_dbus"]
1775
1779
    use_ipv6 = server_settings["use_ipv6"]
1776
 
 
 
1780
    
1777
1781
    if server_settings["servicename"] != "Mandos":
1778
1782
        syslogger.setFormatter(logging.Formatter
1779
1783
                               ('Mandos (%s) [%%(process)d]:'
1840
1844
        level = getattr(logging, debuglevel.upper())
1841
1845
        syslogger.setLevel(level)
1842
1846
        console.setLevel(level)
1843
 
 
 
1847
    
1844
1848
    if debug:
1845
1849
        # Enable all possible GnuTLS debugging
1846
1850
        
1933
1937
        del pidfilename
1934
1938
        
1935
1939
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1936
 
 
 
1940
    
1937
1941
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1938
1942
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())
1939
1943
    
2060
2064
    # Must run before the D-Bus bus name gets deregistered
2061
2065
    cleanup()
2062
2066
 
 
2067
 
2063
2068
if __name__ == '__main__':
2064
2069
    main()