/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-02-27 17:26:35 UTC
  • Revision ID: teddy@fukt.bsnet.se-20110227172635-hw1sire7k3vuo1co
Update copyright year to "2011" wherever appropriate.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
import SocketServer as socketserver
38
38
import socket
39
 
import argparse
 
39
import optparse
40
40
import datetime
41
41
import errno
42
42
import gnutls.crypto
82
82
        SO_BINDTODEVICE = None
83
83
 
84
84
 
85
 
version = "1.3.0"
 
85
version = "1.2.3"
86
86
 
87
87
#logger = logging.getLogger('mandos')
88
88
logger = logging.Logger('mandos')
151
151
        self.group = None       # our entry group
152
152
        self.server = None
153
153
        self.bus = bus
154
 
        self.entry_group_state_changed_match = None
155
154
    def rename(self):
156
155
        """Derived from the Avahi example code"""
157
156
        if self.rename_count >= self.max_renames:
169
168
        self.remove()
170
169
        try:
171
170
            self.add()
172
 
        except dbus.exceptions.DBusException as error:
 
171
        except dbus.exceptions.DBusException, error:
173
172
            logger.critical("DBusException: %s", error)
174
173
            self.cleanup()
175
174
            os._exit(1)
176
175
        self.rename_count += 1
177
176
    def remove(self):
178
177
        """Derived from the Avahi example code"""
179
 
        if self.entry_group_state_changed_match is not None:
180
 
            self.entry_group_state_changed_match.remove()
181
 
            self.entry_group_state_changed_match = None
182
178
        if self.group is not None:
183
179
            self.group.Reset()
184
180
    def add(self):
185
181
        """Derived from the Avahi example code"""
186
 
        self.remove()
187
182
        if self.group is None:
188
183
            self.group = dbus.Interface(
189
184
                self.bus.get_object(avahi.DBUS_NAME,
190
185
                                    self.server.EntryGroupNew()),
191
186
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
192
 
        self.entry_group_state_changed_match = (
193
 
            self.group.connect_to_signal(
194
 
                'StateChanged', self .entry_group_state_changed))
 
187
            self.group.connect_to_signal('StateChanged',
 
188
                                         self
 
189
                                         .entry_group_state_changed)
195
190
        logger.debug("Adding Zeroconf service '%s' of type '%s' ...",
196
191
                     self.name, self.type)
197
192
        self.group.AddService(
220
215
    def cleanup(self):
221
216
        """Derived from the Avahi example code"""
222
217
        if self.group is not None:
223
 
            try:
224
 
                self.group.Free()
225
 
            except (dbus.exceptions.UnknownMethodException,
226
 
                    dbus.exceptions.DBusException) as e:
227
 
                pass
 
218
            self.group.Free()
228
219
            self.group = None
229
 
        self.remove()
230
 
    def server_state_changed(self, state, error=None):
 
220
    def server_state_changed(self, state):
231
221
        """Derived from the Avahi example code"""
232
222
        logger.debug("Avahi server state change: %i", state)
233
 
        bad_states = { avahi.SERVER_INVALID:
234
 
                           "Zeroconf server invalid",
235
 
                       avahi.SERVER_REGISTERING: None,
236
 
                       avahi.SERVER_COLLISION:
237
 
                           "Zeroconf server name collision",
238
 
                       avahi.SERVER_FAILURE:
239
 
                           "Zeroconf server failure" }
240
 
        if state in bad_states:
241
 
            if bad_states[state] is not None:
242
 
                if error is None:
243
 
                    logger.error(bad_states[state])
244
 
                else:
245
 
                    logger.error(bad_states[state] + ": %r", error)
246
 
            self.cleanup()
 
223
        if state == avahi.SERVER_COLLISION:
 
224
            logger.error("Zeroconf server name collision")
 
225
            self.remove()
247
226
        elif state == avahi.SERVER_RUNNING:
248
227
            self.add()
249
 
        else:
250
 
            if error is None:
251
 
                logger.debug("Unknown state: %r", state)
252
 
            else:
253
 
                logger.debug("Unknown state: %r: %r", state, error)
254
228
    def activate(self):
255
229
        """Derived from the Avahi example code"""
256
230
        if self.server is None:
257
231
            self.server = dbus.Interface(
258
232
                self.bus.get_object(avahi.DBUS_NAME,
259
 
                                    avahi.DBUS_PATH_SERVER,
260
 
                                    follow_name_owner_changes=True),
 
233
                                    avahi.DBUS_PATH_SERVER),
261
234
                avahi.DBUS_INTERFACE_SERVER)
262
235
        self.server.connect_to_signal("StateChanged",
263
236
                                 self.server_state_changed)
472
445
        # If a checker exists, make sure it is not a zombie
473
446
        try:
474
447
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
475
 
        except (AttributeError, OSError) as error:
 
448
        except (AttributeError, OSError), error:
476
449
            if (isinstance(error, OSError)
477
450
                and error.errno != errno.ECHILD):
478
451
                raise error
499
472
 
500
473
                try:
501
474
                    command = self.checker_command % escaped_attrs
502
 
                except TypeError as error:
 
475
                except TypeError, error:
503
476
                    logger.error('Could not format string "%s":'
504
477
                                 ' %s', self.checker_command, error)
505
478
                    return True # Try again later
524
497
                if pid:
525
498
                    gobject.source_remove(self.checker_callback_tag)
526
499
                    self.checker_callback(pid, status, command)
527
 
            except OSError as error:
 
500
            except OSError, error:
528
501
                logger.error("Failed to start subprocess: %s",
529
502
                             error)
530
503
        # Re-run this periodically if run by gobject.timeout_add
543
516
            #time.sleep(0.5)
544
517
            #if self.checker.poll() is None:
545
518
            #    os.kill(self.checker.pid, signal.SIGKILL)
546
 
        except OSError as error:
 
519
        except OSError, error:
547
520
            if error.errno != errno.ESRCH: # No such process
548
521
                raise
549
522
        self.checker = None
731
704
            xmlstring = document.toxml("utf-8")
732
705
            document.unlink()
733
706
        except (AttributeError, xml.dom.DOMException,
734
 
                xml.parsers.expat.ExpatError) as error:
 
707
                xml.parsers.expat.ExpatError), error:
735
708
            logger.error("Failed to override Introspection method",
736
709
                         error)
737
710
        return xmlstring
840
813
                                       *args, **kwargs)
841
814
    
842
815
    def checked_ok(self, *args, **kwargs):
843
 
        Client.checked_ok(self, *args, **kwargs)
 
816
        r = Client.checked_ok(self, *args, **kwargs)
844
817
        # Emit D-Bus signal
845
818
        self.PropertyChanged(
846
819
            dbus.String("LastCheckedOK"),
847
820
            (self._datetime_to_dbus(self.last_checked_ok,
848
821
                                    variant_level=1)))
 
822
        return r
849
823
    
850
824
    def need_approval(self, *args, **kwargs):
851
825
        r = Client.need_approval(self, *args, **kwargs)
948
922
    # CheckedOK - method
949
923
    @dbus.service.method(_interface)
950
924
    def CheckedOK(self):
951
 
        self.checked_ok()
 
925
        return self.checked_ok()
952
926
    
953
927
    # Enable - method
954
928
    @dbus.service.method(_interface)
1230
1204
            try:
1231
1205
                if int(line.strip().split()[0]) > 1:
1232
1206
                    raise RuntimeError
1233
 
            except (ValueError, IndexError, RuntimeError) as error:
 
1207
            except (ValueError, IndexError, RuntimeError), error:
1234
1208
                logger.error("Unknown protocol version: %s", error)
1235
1209
                return
1236
1210
 
1237
1211
            # Start GnuTLS connection
1238
1212
            try:
1239
1213
                session.handshake()
1240
 
            except gnutls.errors.GNUTLSError as error:
 
1214
            except gnutls.errors.GNUTLSError, error:
1241
1215
                logger.warning("Handshake failed: %s", error)
1242
1216
                # Do not run session.bye() here: the session is not
1243
1217
                # established.  Just abandon the request.
1249
1223
                try:
1250
1224
                    fpr = self.fingerprint(self.peer_certificate
1251
1225
                                           (session))
1252
 
                except (TypeError,
1253
 
                        gnutls.errors.GNUTLSError) as error:
 
1226
                except (TypeError, gnutls.errors.GNUTLSError), error:
1254
1227
                    logger.warning("Bad certificate: %s", error)
1255
1228
                    return
1256
1229
                logger.debug("Fingerprint: %s", fpr)
1268
1241
                
1269
1242
                while True:
1270
1243
                    if not client.enabled:
1271
 
                        logger.info("Client %s is disabled",
 
1244
                        logger.warning("Client %s is disabled",
1272
1245
                                       client.name)
1273
1246
                        if self.server.use_dbus:
1274
1247
                            # Emit D-Bus signal
1319
1292
                while sent_size < len(client.secret):
1320
1293
                    try:
1321
1294
                        sent = session.send(client.secret[sent_size:])
1322
 
                    except gnutls.errors.GNUTLSError as error:
 
1295
                    except (gnutls.errors.GNUTLSError), error:
1323
1296
                        logger.warning("gnutls send failed")
1324
1297
                        return
1325
1298
                    logger.debug("Sent: %d, remaining: %d",
1339
1312
                    client.approvals_pending -= 1
1340
1313
                try:
1341
1314
                    session.bye()
1342
 
                except gnutls.errors.GNUTLSError as error:
 
1315
                except (gnutls.errors.GNUTLSError), error:
1343
1316
                    logger.warning("GnuTLS bye failed")
1344
1317
    
1345
1318
    @staticmethod
1469
1442
                                           SO_BINDTODEVICE,
1470
1443
                                           str(self.interface
1471
1444
                                               + '\0'))
1472
 
                except socket.error as error:
 
1445
                except socket.error, error:
1473
1446
                    if error[0] == errno.EPERM:
1474
1447
                        logger.error("No permission to"
1475
1448
                                     " bind to interface %s",
1569
1542
                    client = c
1570
1543
                    break
1571
1544
            else:
1572
 
                logger.info("Client not found for fingerprint: %s, ad"
1573
 
                            "dress: %s", fpr, address)
 
1545
                logger.warning("Client not found for fingerprint: %s, ad"
 
1546
                               "dress: %s", fpr, address)
1574
1547
                if self.use_dbus:
1575
1548
                    # Emit D-Bus signal
1576
1549
                    mandos_dbus_service.ClientNotFound(fpr, address[0])
1640
1613
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1641
1614
            else:
1642
1615
                raise ValueError("Unknown suffix %r" % suffix)
1643
 
        except (ValueError, IndexError) as e:
 
1616
        except (ValueError, IndexError), e:
1644
1617
            raise ValueError(*(e.args))
1645
1618
        timevalue += delta
1646
1619
    return timevalue
1700
1673
    ##################################################################
1701
1674
    # Parsing of options, both command line and config file
1702
1675
    
1703
 
    parser = argparse.ArgumentParser()
1704
 
    parser.add_argument("-v", "--version", action="version",
1705
 
                        version = "%%(prog)s %s" % version,
1706
 
                        help="show version number and exit")
1707
 
    parser.add_argument("-i", "--interface", metavar="IF",
1708
 
                        help="Bind to interface IF")
1709
 
    parser.add_argument("-a", "--address",
1710
 
                        help="Address to listen for requests on")
1711
 
    parser.add_argument("-p", "--port", type=int,
1712
 
                        help="Port number to receive requests on")
1713
 
    parser.add_argument("--check", action="store_true",
1714
 
                        help="Run self-test")
1715
 
    parser.add_argument("--debug", action="store_true",
1716
 
                        help="Debug mode; run in foreground and log"
1717
 
                        " to terminal")
1718
 
    parser.add_argument("--debuglevel", metavar="LEVEL",
1719
 
                        help="Debug level for stdout output")
1720
 
    parser.add_argument("--priority", help="GnuTLS"
1721
 
                        " priority string (see GnuTLS documentation)")
1722
 
    parser.add_argument("--servicename",
1723
 
                        metavar="NAME", help="Zeroconf service name")
1724
 
    parser.add_argument("--configdir",
1725
 
                        default="/etc/mandos", metavar="DIR",
1726
 
                        help="Directory to search for configuration"
1727
 
                        " files")
1728
 
    parser.add_argument("--no-dbus", action="store_false",
1729
 
                        dest="use_dbus", help="Do not provide D-Bus"
1730
 
                        " system bus interface")
1731
 
    parser.add_argument("--no-ipv6", action="store_false",
1732
 
                        dest="use_ipv6", help="Do not use IPv6")
1733
 
    options = parser.parse_args()
 
1676
    parser = optparse.OptionParser(version = "%%prog %s" % version)
 
1677
    parser.add_option("-i", "--interface", type="string",
 
1678
                      metavar="IF", help="Bind to interface IF")
 
1679
    parser.add_option("-a", "--address", type="string",
 
1680
                      help="Address to listen for requests on")
 
1681
    parser.add_option("-p", "--port", type="int",
 
1682
                      help="Port number to receive requests on")
 
1683
    parser.add_option("--check", action="store_true",
 
1684
                      help="Run self-test")
 
1685
    parser.add_option("--debug", action="store_true",
 
1686
                      help="Debug mode; run in foreground and log to"
 
1687
                      " terminal")
 
1688
    parser.add_option("--debuglevel", type="string", metavar="LEVEL",
 
1689
                      help="Debug level for stdout output")
 
1690
    parser.add_option("--priority", type="string", help="GnuTLS"
 
1691
                      " priority string (see GnuTLS documentation)")
 
1692
    parser.add_option("--servicename", type="string",
 
1693
                      metavar="NAME", help="Zeroconf service name")
 
1694
    parser.add_option("--configdir", type="string",
 
1695
                      default="/etc/mandos", metavar="DIR",
 
1696
                      help="Directory to search for configuration"
 
1697
                      " files")
 
1698
    parser.add_option("--no-dbus", action="store_false",
 
1699
                      dest="use_dbus", help="Do not provide D-Bus"
 
1700
                      " system bus interface")
 
1701
    parser.add_option("--no-ipv6", action="store_false",
 
1702
                      dest="use_ipv6", help="Do not use IPv6")
 
1703
    options = parser.parse_args()[0]
1734
1704
    
1735
1705
    if options.check:
1736
1706
        import doctest
1843
1813
    try:
1844
1814
        os.setgid(gid)
1845
1815
        os.setuid(uid)
1846
 
    except OSError as error:
 
1816
    except OSError, error:
1847
1817
        if error[0] != errno.EPERM:
1848
1818
            raise error
1849
1819
    
1893
1863
        try:
1894
1864
            bus_name = dbus.service.BusName("se.bsnet.fukt.Mandos",
1895
1865
                                            bus, do_not_queue=True)
1896
 
        except dbus.exceptions.NameExistsException as e:
 
1866
        except dbus.exceptions.NameExistsException, e:
1897
1867
            logger.error(unicode(e) + ", disabling D-Bus")
1898
1868
            use_dbus = False
1899
1869
            server_settings["use_dbus"] = False
2049
2019
        # From the Avahi example code
2050
2020
        try:
2051
2021
            service.activate()
2052
 
        except dbus.exceptions.DBusException as error:
 
2022
        except dbus.exceptions.DBusException, error:
2053
2023
            logger.critical("DBusException: %s", error)
2054
2024
            cleanup()
2055
2025
            sys.exit(1)
2062
2032
        
2063
2033
        logger.debug("Starting main loop")
2064
2034
        main_loop.run()
2065
 
    except AvahiError as error:
 
2035
    except AvahiError, error:
2066
2036
        logger.critical("AvahiError: %s", error)
2067
2037
        cleanup()
2068
2038
        sys.exit(1)