diff options
author | Rob Austein <sra@hactrn.net> | 2012-01-13 17:35:08 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2012-01-13 17:35:08 +0000 |
commit | 1bcb4c3e5b1f62ce2417985649caae76a0edd385 (patch) | |
tree | 85556eabd260c11895510936bfaca650c64b1e4e | |
parent | e5662c723c93bbdd0d5b752d96fea038ab8b4da0 (diff) | |
parent | 38c391ec3d2a41407500d77c89d08b3fa9852f09 (diff) |
Synch changes from trunk/.
svn path=/branches/tk100/; revision=4151
-rw-r--r-- | openssl/Makefile.in | 2 | ||||
-rw-r--r-- | openssl/openssl-1.0.0e.tar.gz | bin | 4040229 -> 0 bytes | |||
-rw-r--r-- | openssl/openssl-1.0.0f.tar.gz | bin | 0 -> 4043367 bytes | |||
-rwxr-xr-x | openssl/update-snapshot.sh | 2 | ||||
-rwxr-xr-x | rtr-origin/rtr-origin.py | 116 |
5 files changed, 99 insertions, 21 deletions
diff --git a/openssl/Makefile.in b/openssl/Makefile.in index 59f5d6fd..b5085c17 100644 --- a/openssl/Makefile.in +++ b/openssl/Makefile.in @@ -1,6 +1,6 @@ # $Id$ -VERSION = 1.0.0e +VERSION = 1.0.0f OPENSSL_CONFIG_COMMAND = @OPENSSL_CONFIG_COMMAND@ OPENSSL_BUILD_DIRECTORY = ${abs_builddir}/openssl diff --git a/openssl/openssl-1.0.0e.tar.gz b/openssl/openssl-1.0.0e.tar.gz Binary files differdeleted file mode 100644 index 346af252..00000000 --- a/openssl/openssl-1.0.0e.tar.gz +++ /dev/null diff --git a/openssl/openssl-1.0.0f.tar.gz b/openssl/openssl-1.0.0f.tar.gz Binary files differnew file mode 100644 index 00000000..7bce05eb --- /dev/null +++ b/openssl/openssl-1.0.0f.tar.gz diff --git a/openssl/update-snapshot.sh b/openssl/update-snapshot.sh index a8723c10..94932f59 100755 --- a/openssl/update-snapshot.sh +++ b/openssl/update-snapshot.sh @@ -6,7 +6,7 @@ #version="1.0.0-stable-SNAP-$(date +%Y%m%d)" -version="1.0.0e" +version="1.0.0f" tarball="openssl-${version}.tar.gz" diff --git a/rtr-origin/rtr-origin.py b/rtr-origin/rtr-origin.py index 5ebc0401..3b6ec145 100755 --- a/rtr-origin/rtr-origin.py +++ b/rtr-origin/rtr-origin.py @@ -178,6 +178,36 @@ class read_buffer(object): """ return self.callback(self) +class PDUException(Exception): + """ + Parent exception type for exceptions that signal particular protocol + errors. String value of exception instance will be the message to + put in the error_report PDU, error_report_code value of exception + will be the numeric code to use. + """ + + def __init__(self, msg = None, pdu = None): + assert msg is None or isinstance(msg, (str, unicode)) + self.error_report_msg = msg + self.error_report_pdu = pdu + + def __str__(self): + return self.error_report_msg or self.__class__.__name__ + + def make_error_report(self): + return error_report(errno = self.error_report_code, + errmsg = self.error_report_msg, + errpdu = self.error_report_pdu) + +class UnsupportedProtocolVersion(PDUException): + error_report_code = 4 + +class UnsupportedPDUType(PDUException): + error_report_code = 5 + +class CorruptData(PDUException): + error_report_code = 0 + class pdu(object): """ Object representing a generic PDU in the rpki-router protocol. @@ -209,8 +239,15 @@ class pdu(object): return None assert reader.available() >= cls.header_struct.size version, pdu_type, whatever, length = cls.header_struct.unpack(reader.buffer[:cls.header_struct.size]) - assert version == cls.version, "PDU version is %d, expected %d" % (version, cls.version) - assert length >= 8 + if version != cls.version: + raise UnsupportedProtocolVersion( + "Received PDU version %d, expected %d" % (version, cls.version)) + if pdu_type not in cls.pdu_map: + raise UnsupportedPDUType( + "Received unsupported PDU type %d" % pdu_type) + if length < 8: + raise CorruptData( + "Received PDU with length %d, which is too short to be valid" % length) self = cls.pdu_map[pdu_type]() return reader.update(need = length, callback = self.got_pdu) @@ -267,7 +304,8 @@ class pdu_with_serial(pdu): return None b = reader.get(self.header_struct.size) version, pdu_type, self.nonce, length, self.serial = self.header_struct.unpack(b) - assert length == 12 + if length != 12: + raise CorruptData("PDU length of %d can't be right" % length, pdu = self) assert b == self.to_pdu() return self @@ -299,7 +337,8 @@ class pdu_nonce(pdu): return None b = reader.get(self.header_struct.size) version, pdu_type, self.nonce, length = self.header_struct.unpack(b) - assert length == 8 + if length != 8: + raise CorruptData("PDU length of %d can't be right" % length, pdu = self) assert b == self.to_pdu() return self @@ -326,8 +365,10 @@ class pdu_empty(pdu): return None b = reader.get(self.header_struct.size) version, pdu_type, zero, length = self.header_struct.unpack(b) - assert zero == 0 - assert length == 8 + if zero != 0: + raise CorruptData("Must-be-zero field isn't zero" % length, pdu = self) + if length != 8: + raise CorruptData("PDU length of %d can't be right" % length, pdu = self) assert b == self.to_pdu() return self @@ -487,11 +528,15 @@ class prefix(pdu): """ Check attributes to make sure they're within range. """ - assert self.announce in (0, 1) - assert self.prefixlen >= 0 and self.prefixlen <= self.addr_type.size * 8 - assert self.max_prefixlen >= self.prefixlen and self.max_prefixlen <= self.addr_type.size * 8 + if self.announce not in (0, 1): + raise CorruptData("Announce value %d is neither zero nor one" % self.announce, pdu = self) + if self.prefixlen < 0 or self.prefixlen > self.addr_type.size * 8: + raise CorruptData("Implausible prefix length %d" % self.prefixlen, pdu = self) + if self.max_prefixlen < self.prefixlen or self.max_prefixlen > self.addr_type.size * 8: + raise CorruptData("Implausible max prefix length %d" % self.max_prefixlen, pdu = self) pdulen = self.header_struct.size + self.addr_type.size + self.asnum_struct.size - assert len(self.to_pdu()) == pdulen, "Expected %d byte PDU, got %d" % pd(pdulen, len(self.to_pdu())) + if len(self.to_pdu()) != pdulen: + raise CorruptData("Expected %d byte PDU, got %d" % (pdulen, len(self.to_pdu())), pdu = self) def to_pdu(self, announce = None): """ @@ -519,7 +564,8 @@ class prefix(pdu): b2 = reader.get(self.addr_type.size) b3 = reader.get(self.asnum_struct.size) version, pdu_type, length, self.announce, self.prefixlen, self.max_prefixlen = self.header_struct.unpack(b1) - assert length == len(b1) + len(b2) + len(b3) + if length != len(b1) + len(b2) + len(b3): + raise CorruptData("Got PDU length %d, expected %d" % (length, len(b1) + len(b2) + len(b3)), pdu = self) self.prefix = self.addr_type(value = b2) self.asn = self.asnum_struct.unpack(b3)[0] assert b1 + b2 + b3 == self.to_pdu() @@ -605,7 +651,7 @@ class error_report(pdu): 6 : "Withdrawal of Unknown Record", 7 : "Duplicate Announcement Received" } - assert set(errors).isdisjoint(set(fatal)) + assert set(errors) & set(fatal) == set() errors.update(fatal) @@ -631,7 +677,7 @@ class error_report(pdu): def to_pdu(self): """ - Generate the wire format PDU for this prefix. + Generate the wire format PDU for this error report. """ if self._pdu is None: assert isinstance(self.errno, int) @@ -656,7 +702,9 @@ class error_report(pdu): remaining = length - self.header_struct.size self.pdulen, self.errpdu, remaining = self.read_counted_string(reader, remaining) self.errlen, self.errmsg, remaining = self.read_counted_string(reader, remaining) - assert length == self.header_struct.size + self.string_struct.size * 2 + self.pdulen + self.errlen + if length != self.header_struct.size + self.string_struct.size * 2 + self.pdulen + self.errlen: + raise CorruptData("Got PDU length %d, expected %d" % ( + length, self.header_struct.size + self.string_struct.size * 2 + self.pdulen + self.errlen)) assert header + self.to_counted_string(self.errpdu) + self.to_counted_string(self.errmsg.encode("utf8")) == self.to_pdu() return self @@ -946,12 +994,17 @@ class pdu_channel(asynchat.async_chat): """ Start read of a new PDU. """ - p = pdu.read_pdu(self.reader) - while p is not None: - self.deliver_pdu(p) + try: p = pdu.read_pdu(self.reader) - assert not self.reader.ready() - self.set_terminator(self.reader.needed()) + while p is not None: + self.deliver_pdu(p) + p = pdu.read_pdu(self.reader) + except PDUException, e: + self.push_pdu(e.make_error_report()) + self.close_when_done() + else: + assert not self.reader.ready() + self.set_terminator(self.reader.needed()) def collect_incoming_data(self, data): """ @@ -1187,6 +1240,25 @@ class client_channel(pdu_channel): proc = subprocess.Popen(argv, stdin = s[0], stdout = s[0], close_fds = True), killsig = signal.SIGINT) + @classmethod + def tls(cls, host, port): + """ + Set up TLS connection and start listening for first PDU. + + NB: This uses OpenSSL's "s_client" command, which does not + check server certificates properly, so this is not suitable for + production use. Fixing this would be a trivial change, it just + requires using a client program which does check certificates + properly (eg, gnutls-cli, or stunnel's client mode if that works + for such purposes this week). + """ + args = ("openssl", "s_client", "-tls1", "-quiet", "-connect", "%s:%s" % (host, port)) + blather("[Running: %s]" % " ".join(args)) + s = socket.socketpair() + return cls(sock = s[1], + proc = subprocess.Popen(args, stdin = s[0], stdout = s[0], close_fds = True), + killsig = signal.SIGKILL) + def deliver_pdu(self, pdu): """ Handle received PDU. @@ -1519,6 +1591,10 @@ def client_main(argv): direct (and completely insecure!) TCP connection to the server. The remaining arguments should be a hostname (or IP address) and a TCP port number. + + If the first argument is "tls", the client will attempt to open a TLS connection to the server. The + remaining arguments should be a hostname (or IP address) and a TCP + port number. """ blather("[Startup]") @@ -1530,6 +1606,8 @@ def client_main(argv): client = client_channel.ssh(*argv[1:]) elif argv[0] == "tcp" and len(argv) == 3: client = client_channel.tcp(*argv[1:]) + elif argv[0] == "tls" and len(argv) == 3: + client = client_channel.tls(*argv[1:]) else: sys.exit("Unexpected arguments: %r" % (argv,)) while True: |