/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)
177
176
    def remove(self):
178
177
        """Derived from the Avahi example code"""
179
178
        if self.group is not None:
180
 
            try:
181
 
                self.group.Free()
182
 
            except (dbus.exceptions.UnknownMethodException,
183
 
                    dbus.exceptions.DBusException) as e:
184
 
                pass
185
 
            self.group = None
186
 
        if self.entry_group_state_changed_match is not None:
187
 
            self.entry_group_state_changed_match.remove()
188
 
            self.entry_group_state_changed_match = None
 
179
            self.group.Reset()
189
180
    def add(self):
190
181
        """Derived from the Avahi example code"""
191
 
        self.remove()
192
 
        self.group = dbus.Interface(
193
 
            self.bus.get_object(avahi.DBUS_NAME,
194
 
                                self.server.EntryGroupNew(),
195
 
                                follow_name_owner_changes=True),
196
 
            avahi.DBUS_INTERFACE_ENTRY_GROUP)
197
 
        self.entry_group_state_changed_match = (
198
 
            self.group.connect_to_signal(
199
 
                'StateChanged', self .entry_group_state_changed))
 
182
        if self.group is None:
 
183
            self.group = dbus.Interface(
 
184
                self.bus.get_object(avahi.DBUS_NAME,
 
185
                                    self.server.EntryGroupNew()),
 
186
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
 
187
            self.group.connect_to_signal('StateChanged',
 
188
                                         self
 
189
                                         .entry_group_state_changed)
200
190
        logger.debug("Adding Zeroconf service '%s' of type '%s' ...",
201
191
                     self.name, self.type)
202
192
        self.group.AddService(
224
214
                                  % unicode(error))
225
215
    def cleanup(self):
226
216
        """Derived from the Avahi example code"""
227
 
        self.remove()
228
 
    def server_state_changed(self, state, error=None):
 
217
        if self.group is not None:
 
218
            self.group.Free()
 
219
            self.group = None
 
220
    def server_state_changed(self, state):
229
221
        """Derived from the Avahi example code"""
230
222
        logger.debug("Avahi server state change: %i", state)
231
 
        bad_states = { avahi.SERVER_INVALID:
232
 
                           "Zeroconf server invalid",
233
 
                       avahi.SERVER_REGISTERING: None,
234
 
                       avahi.SERVER_COLLISION:
235
 
                           "Zeroconf server name collision",
236
 
                       avahi.SERVER_FAILURE:
237
 
                           "Zeroconf server failure" }
238
 
        if state in bad_states:
239
 
            if bad_states[state]:
240
 
                logger.error(bad_states[state])
 
223
        if state == avahi.SERVER_COLLISION:
 
224
            logger.error("Zeroconf server name collision")
241
225
            self.remove()
242
226
        elif state == avahi.SERVER_RUNNING:
243
227
            self.add()
244
 
        else:
245
 
            logger.debug("Unknown state: %r", state)
246
228
    def activate(self):
247
229
        """Derived from the Avahi example code"""
248
230
        if self.server is None:
249
231
            self.server = dbus.Interface(
250
232
                self.bus.get_object(avahi.DBUS_NAME,
251
 
                                    avahi.DBUS_PATH_SERVER,
252
 
                                    follow_name_owner_changes=True),
 
233
                                    avahi.DBUS_PATH_SERVER),
253
234
                avahi.DBUS_INTERFACE_SERVER)
254
235
        self.server.connect_to_signal("StateChanged",
255
236
                                 self.server_state_changed)
464
445
        # If a checker exists, make sure it is not a zombie
465
446
        try:
466
447
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
467
 
        except (AttributeError, OSError) as error:
 
448
        except (AttributeError, OSError), error:
468
449
            if (isinstance(error, OSError)
469
450
                and error.errno != errno.ECHILD):
470
451
                raise error
491
472
 
492
473
                try:
493
474
                    command = self.checker_command % escaped_attrs
494
 
                except TypeError as error:
 
475
                except TypeError, error:
495
476
                    logger.error('Could not format string "%s":'
496
477
                                 ' %s', self.checker_command, error)
497
478
                    return True # Try again later
516
497
                if pid:
517
498
                    gobject.source_remove(self.checker_callback_tag)
518
499
                    self.checker_callback(pid, status, command)
519
 
            except OSError as error:
 
500
            except OSError, error:
520
501
                logger.error("Failed to start subprocess: %s",
521
502
                             error)
522
503
        # Re-run this periodically if run by gobject.timeout_add
535
516
            #time.sleep(0.5)
536
517
            #if self.checker.poll() is None:
537
518
            #    os.kill(self.checker.pid, signal.SIGKILL)
538
 
        except OSError as error:
 
519
        except OSError, error:
539
520
            if error.errno != errno.ESRCH: # No such process
540
521
                raise
541
522
        self.checker = None
723
704
            xmlstring = document.toxml("utf-8")
724
705
            document.unlink()
725
706
        except (AttributeError, xml.dom.DOMException,
726
 
                xml.parsers.expat.ExpatError) as error:
 
707
                xml.parsers.expat.ExpatError), error:
727
708
            logger.error("Failed to override Introspection method",
728
709
                         error)
729
710
        return xmlstring
832
813
                                       *args, **kwargs)
833
814
    
834
815
    def checked_ok(self, *args, **kwargs):
835
 
        Client.checked_ok(self, *args, **kwargs)
 
816
        r = Client.checked_ok(self, *args, **kwargs)
836
817
        # Emit D-Bus signal
837
818
        self.PropertyChanged(
838
819
            dbus.String("LastCheckedOK"),
839
820
            (self._datetime_to_dbus(self.last_checked_ok,
840
821
                                    variant_level=1)))
 
822
        return r
841
823
    
842
824
    def need_approval(self, *args, **kwargs):
843
825
        r = Client.need_approval(self, *args, **kwargs)
940
922
    # CheckedOK - method
941
923
    @dbus.service.method(_interface)
942
924
    def CheckedOK(self):
943
 
        self.checked_ok()
 
925
        return self.checked_ok()
944
926
    
945
927
    # Enable - method
946
928
    @dbus.service.method(_interface)
1222
1204
            try:
1223
1205
                if int(line.strip().split()[0]) > 1:
1224
1206
                    raise RuntimeError
1225
 
            except (ValueError, IndexError, RuntimeError) as error:
 
1207
            except (ValueError, IndexError, RuntimeError), error:
1226
1208
                logger.error("Unknown protocol version: %s", error)
1227
1209
                return
1228
1210
 
1229
1211
            # Start GnuTLS connection
1230
1212
            try:
1231
1213
                session.handshake()
1232
 
            except gnutls.errors.GNUTLSError as error:
 
1214
            except gnutls.errors.GNUTLSError, error:
1233
1215
                logger.warning("Handshake failed: %s", error)
1234
1216
                # Do not run session.bye() here: the session is not
1235
1217
                # established.  Just abandon the request.
1241
1223
                try:
1242
1224
                    fpr = self.fingerprint(self.peer_certificate
1243
1225
                                           (session))
1244
 
                except (TypeError,
1245
 
                        gnutls.errors.GNUTLSError) as error:
 
1226
                except (TypeError, gnutls.errors.GNUTLSError), error:
1246
1227
                    logger.warning("Bad certificate: %s", error)
1247
1228
                    return
1248
1229
                logger.debug("Fingerprint: %s", fpr)
1311
1292
                while sent_size < len(client.secret):
1312
1293
                    try:
1313
1294
                        sent = session.send(client.secret[sent_size:])
1314
 
                    except gnutls.errors.GNUTLSError as error:
 
1295
                    except (gnutls.errors.GNUTLSError), error:
1315
1296
                        logger.warning("gnutls send failed")
1316
1297
                        return
1317
1298
                    logger.debug("Sent: %d, remaining: %d",
1331
1312
                    client.approvals_pending -= 1
1332
1313
                try:
1333
1314
                    session.bye()
1334
 
                except gnutls.errors.GNUTLSError as error:
 
1315
                except (gnutls.errors.GNUTLSError), error:
1335
1316
                    logger.warning("GnuTLS bye failed")
1336
1317
    
1337
1318
    @staticmethod
1461
1442
                                           SO_BINDTODEVICE,
1462
1443
                                           str(self.interface
1463
1444
                                               + '\0'))
1464
 
                except socket.error as error:
 
1445
                except socket.error, error:
1465
1446
                    if error[0] == errno.EPERM:
1466
1447
                        logger.error("No permission to"
1467
1448
                                     " bind to interface %s",
1632
1613
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1633
1614
            else:
1634
1615
                raise ValueError("Unknown suffix %r" % suffix)
1635
 
        except (ValueError, IndexError) as e:
 
1616
        except (ValueError, IndexError), e:
1636
1617
            raise ValueError(*(e.args))
1637
1618
        timevalue += delta
1638
1619
    return timevalue
1692
1673
    ##################################################################
1693
1674
    # Parsing of options, both command line and config file
1694
1675
    
1695
 
    parser = argparse.ArgumentParser()
1696
 
    parser.add_argument("-v", "--version", action="version",
1697
 
                        version = "%%(prog)s %s" % version,
1698
 
                        help="show version number and exit")
1699
 
    parser.add_argument("-i", "--interface", metavar="IF",
1700
 
                        help="Bind to interface IF")
1701
 
    parser.add_argument("-a", "--address",
1702
 
                        help="Address to listen for requests on")
1703
 
    parser.add_argument("-p", "--port", type=int,
1704
 
                        help="Port number to receive requests on")
1705
 
    parser.add_argument("--check", action="store_true",
1706
 
                        help="Run self-test")
1707
 
    parser.add_argument("--debug", action="store_true",
1708
 
                        help="Debug mode; run in foreground and log"
1709
 
                        " to terminal")
1710
 
    parser.add_argument("--debuglevel", metavar="LEVEL",
1711
 
                        help="Debug level for stdout output")
1712
 
    parser.add_argument("--priority", help="GnuTLS"
1713
 
                        " priority string (see GnuTLS documentation)")
1714
 
    parser.add_argument("--servicename",
1715
 
                        metavar="NAME", help="Zeroconf service name")
1716
 
    parser.add_argument("--configdir",
1717
 
                        default="/etc/mandos", metavar="DIR",
1718
 
                        help="Directory to search for configuration"
1719
 
                        " files")
1720
 
    parser.add_argument("--no-dbus", action="store_false",
1721
 
                        dest="use_dbus", help="Do not provide D-Bus"
1722
 
                        " system bus interface")
1723
 
    parser.add_argument("--no-ipv6", action="store_false",
1724
 
                        dest="use_ipv6", help="Do not use IPv6")
1725
 
    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]
1726
1704
    
1727
1705
    if options.check:
1728
1706
        import doctest
1835
1813
    try:
1836
1814
        os.setgid(gid)
1837
1815
        os.setuid(uid)
1838
 
    except OSError as error:
 
1816
    except OSError, error:
1839
1817
        if error[0] != errno.EPERM:
1840
1818
            raise error
1841
1819
    
1885
1863
        try:
1886
1864
            bus_name = dbus.service.BusName("se.bsnet.fukt.Mandos",
1887
1865
                                            bus, do_not_queue=True)
1888
 
        except dbus.exceptions.NameExistsException as e:
 
1866
        except dbus.exceptions.NameExistsException, e:
1889
1867
            logger.error(unicode(e) + ", disabling D-Bus")
1890
1868
            use_dbus = False
1891
1869
            server_settings["use_dbus"] = False
2041
2019
        # From the Avahi example code
2042
2020
        try:
2043
2021
            service.activate()
2044
 
        except dbus.exceptions.DBusException as error:
 
2022
        except dbus.exceptions.DBusException, error:
2045
2023
            logger.critical("DBusException: %s", error)
2046
2024
            cleanup()
2047
2025
            sys.exit(1)
2054
2032
        
2055
2033
        logger.debug("Starting main loop")
2056
2034
        main_loop.run()
2057
 
    except AvahiError as error:
 
2035
    except AvahiError, error:
2058
2036
        logger.critical("AvahiError: %s", error)
2059
2037
        cleanup()
2060
2038
        sys.exit(1)