aboutsummaryrefslogtreecommitdiff
path: root/rpki/old_irdbd.py
blob: c08ce362307c90963d136f4c21f0bdbb8a24b7db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
SSLeay 0.8.4c 03-Aug-1999
built on Tue Aug  3 09:49:58 EST 1999
options:bn(64,32) md2(int) rc4(ptr,int) des(idx,cisc,4,long) idea(int) blowfish(
ptr2)
C flags:cl /W3 /WX /G5 /Ox /O2 /Ob2 /Gs0 /GF /Gy /nologo -DWIN32 -DL_ENDIAN -DBN
_ASM -DMD5_ASM -DSHA1_ASM
The 'numbers' are in 1000s of bytes per second processed.
type              8 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
md2                93.07k      258.38k      349.03k      382.83k      392.87k
mdc2              245.80k      259.02k      259.34k      259.16k      260.14k
md5              1103.42k     6017.65k    12210.49k    16552.11k    18291.77k
hmac(md5)         520.15k     3394.00k     8761.86k    14593.96k    17742.40k
sha1              538.06k     2726.76k     5242.22k     6821.12k     7426.18k
rc4              8283.90k    10513.09k    10886.38k    10929.50k    10816.75k
des cbc          2073.10k     2232.91k     2251.61k     2256.46k     2232.44k
des ede3          758.85k      782.46k      786.14k      786.08k      781.24k
idea cbc          831.02k      892.63k      901.07k      903.48k      901.85k
rc2 cbc           799.89k      866.09k      873.96k      876.22k      874.03k
blowfish cbc     3835.32k     4418.78k     4511.94k     4494.54k     4416.92k
cast cbc         2974.68k     3272.71k     3313.04k     3335.17k     3261.51k
                  sign    verify
rsa  512 bits   0.0202s   0.0019s
rsa 1024 bits   0.1029s   0.0062s
rsa 2048 bits   0.6770s   0.0220s
rsa 4096 bits   4.8770s   0.0838s
                  sign    verify
dsa  512 bits   0.0191s   0.0364s
dsa 1024 bits   0.0590s   0.1141s
dsa 2048 bits   0.2088s   0.4171s
2' href='#n282'>282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
# $Id$
#
# Copyright (C) 2013--2014  Dragon Research Labs ("DRL")
# Portions copyright (C) 2009--2012  Internet Systems Consortium ("ISC")
# Portions copyright (C) 2007--2008  American Registry for Internet Numbers ("ARIN")
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notices and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND DRL, ISC, AND ARIN DISCLAIM ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL DRL,
# ISC, OR ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""
IR database daemon.

This is the old (pre-Django) version of irdbd, still used by smoketest
and perhaps still useful as a minimal example.  This does NOT work with
the GUI, rpkic, or any of the other more recent tools.
"""

# pylint: skip-file

import os
import time
import logging
import argparse
import urlparse
import rpki.http_simple
import rpki.config
import rpki.resource_set
import rpki.relaxng
import rpki.exceptions
import rpki.left_right
import rpki.log
import rpki.x509

from rpki.mysql_import import MySQLdb

logger = logging.getLogger(__name__)

class main(object):


    def handle_list_resources(self, q_pdu, r_msg):

        r_pdu = rpki.left_right.list_resources_elt()
        r_pdu.tag = q_pdu.tag
        r_pdu.self_handle = q_pdu.self_handle
        r_pdu.child_handle = q_pdu.child_handle

        self.cur.execute(
            """
            SELECT registrant_id, valid_until
            FROM registrant
            WHERE registry_handle = %s AND registrant_handle = %s
            """,
            (q_pdu.self_handle, q_pdu.child_handle))

        if self.cur.rowcount != 1:
            raise rpki.exceptions.NotInDatabase(
                "This query should have produced a single exact match, something's messed up"
                " (rowcount = %d, self_handle = %s, child_handle = %s)"
                % (self.cur.rowcount, q_pdu.self_handle, q_pdu.child_handle))

        registrant_id, valid_until = self.cur.fetchone()

        r_pdu.valid_until = valid_until.strftime("%Y-%m-%dT%H:%M:%SZ")

        r_pdu.asn  = rpki.resource_set.resource_set_as.from_sql(
            self.cur,
            """
            SELECT start_as, end_as
            FROM registrant_asn
            WHERE registrant_id = %s
            """,
            (registrant_id,))

        r_pdu.ipv4 = rpki.resource_set.resource_set_ipv4.from_sql(
            self.cur,
            """
            SELECT start_ip, end_ip
            FROM registrant_net
            WHERE registrant_id = %s AND version = 4
            """,
            (registrant_id,))

        r_pdu.ipv6 = rpki.resource_set.resource_set_ipv6.from_sql(
            self.cur,
            """
            SELECT start_ip, end_ip
            FROM registrant_net
            WHERE registrant_id = %s AND version = 6
            """,
            (registrant_id,))

        r_msg.append(r_pdu)


    def handle_list_roa_requests(self, q_pdu, r_msg):

        self.cur.execute(
            "SELECT roa_request_id, asn FROM roa_request WHERE self_handle = %s",
            (q_pdu.self_handle,))

        for roa_request_id, asn in self.cur.fetchall():

            r_pdu = rpki.left_right.list_roa_requests_elt()
            r_pdu.tag = q_pdu.tag
            r_pdu.self_handle = q_pdu.self_handle
            r_pdu.asn = asn

            r_pdu.ipv4 = rpki.resource_set.roa_prefix_set_ipv4.from_sql(
                self.cur,
                """
                SELECT prefix, prefixlen, max_prefixlen
                FROM roa_request_prefix
                WHERE roa_request_id = %s AND version = 4
                """,
                (roa_request_id,))

            r_pdu.ipv6 = rpki.resource_set.roa_prefix_set_ipv6.from_sql(
                self.cur,
                """
                SELECT prefix, prefixlen, max_prefixlen
                FROM roa_request_prefix
                WHERE roa_request_id = %s AND version = 6
                """,
                (roa_request_id,))

            r_msg.append(r_pdu)


    def handle_list_ghostbuster_requests(self, q_pdu, r_msg):

        self.cur.execute(
            """
            SELECT vcard
            FROM ghostbuster_request
            WHERE self_handle = %s AND parent_handle = %s
            """,
            (q_pdu.self_handle, q_pdu.parent_handle))

        vcards = [result[0] for result in self.cur.fetchall()]

        if not vcards:

            self.cur.execute(
                """
                SELECT vcard
                FROM ghostbuster_request
                WHERE self_handle = %s AND parent_handle IS NULL
                """,
                (q_pdu.self_handle,))

            vcards = [result[0] for result in self.cur.fetchall()]

        for vcard in vcards:
            r_pdu = rpki.left_right.list_ghostbuster_requests_elt()
            r_pdu.tag = q_pdu.tag
            r_pdu.self_handle = q_pdu.self_handle
            r_pdu.parent_handle = q_pdu.parent_handle
            r_pdu.vcard = vcard
            r_msg.append(r_pdu)


    def handle_list_ee_certificate_requests(self, q_pdu, r_msg):

        self.cur.execute(
            """
            SELECT ee_certificate_id, pkcs10, gski, cn, sn, eku, valid_until
            FROM ee_certificate
            WHERE self_handle = %s
            """,
            (q_pdu.self_handle,))

        for ee_certificate_id, pkcs10, gski, cn, sn, eku, valid_until in self.cur.fetchall():

            r_pdu = rpki.left_right.list_ee_certificate_requests_elt()
            r_pdu.tag = q_pdu.tag
            r_pdu.self_handle = q_pdu.self_handle
            r_pdu.valid_until = valid_until.strftime("%Y-%m-%dT%H:%M:%SZ")
            r_pdu.pkcs10      = rpki.x509.PKCS10(DER = pkcs10)
            r_pdu.gski        = gski
            r_pdu.cn          = cn
            r_pdu.sn          = sn
            r_pdu.eku         = eku

            r_pdu.asn = rpki.resource_set.resource_set_as.from_sql(
                self.cur,
                """
                SELECT start_as, end_as
                FROM ee_certificate_asn
                WHERE ee_certificate_id = %s
                """,
                (ee_certificate_id,))

            r_pdu.ipv4 = rpki.resource_set.resource_set_ipv4.from_sql(
                self.cur,
                """
                SELECT start_ip, end_ip
                FROM ee_certificate_net
                WHERE ee_certificate_id = %s AND version = 4
                """,
                (ee_certificate_id,))

            r_pdu.ipv6 = rpki.resource_set.resource_set_ipv6.from_sql(
                self.cur,
                """
                SELECT start_ip, end_ip
                FROM ee_certificate_net
                WHERE ee_certificate_id = %s AND version = 6
                """,
                (ee_certificate_id,))

            r_msg.append(r_pdu)


    handle_dispatch = {
        rpki.left_right.list_resources_elt               : handle_list_resources,
        rpki.left_right.list_roa_requests_elt            : handle_list_roa_requests,
        rpki.left_right.list_ghostbuster_requests_elt    : handle_list_ghostbuster_requests,
        rpki.left_right.list_ee_certificate_requests_elt : handle_list_ee_certificate_requests }

    def handler(self, request, q_der):
        try:

            self.db.ping(True)

            r_msg = rpki.left_right.msg.reply()

            try:

                q_msg = rpki.left_right.cms_msg_saxify(DER = q_der).unwrap((self.bpki_ta, self.rpkid_cert))

                if not isinstance(q_msg, rpki.left_right.msg) or not q_msg.is_query():
                    raise rpki.exceptions.BadQuery("Unexpected %r PDU" % q_msg)

                for q_pdu in q_msg:

                    try:

                        try:
                            h = self.handle_dispatch[type(q_pdu)]
                        except KeyError:
                            raise rpki.exceptions.BadQuery("Unexpected %r PDU" % q_pdu)
                        else:
                            h(self, q_pdu, r_msg)

                    except Exception, e:
                        logger.exception("Exception serving PDU %r", q_pdu)
                        r_msg.append(rpki.left_right.report_error_elt.from_exception(e, q_pdu.self_handle, q_pdu.tag))

            except Exception, e:
                logger.exception("Exception decoding query")
                r_msg.append(rpki.left_right.report_error_elt.from_exception(e))

            request.send_cms_response(rpki.left_right.cms_msg_saxify().wrap(r_msg, self.irdbd_key, self.irdbd_cert))

        except Exception, e:
            logger.exception("Unhandled exception, returning HTTP failure")
            request.send_error(500, "Unhandled exception %s: %s" % (e.__class__.__name__, e))


    def __init__(self):

        os.environ["TZ"] = "UTC"
        time.tzset()

        self.cfg = rpki.config.argparser(section = "irdbd", doc = __doc__)
        self.cfg.add_boolean_argument("--foreground", default = False,
                                      help = "do not daemonize (ignored, old_irdbd never daemonizes)")
        self.cfg.add_logging_arguments()
        args = parser.parse_args()

        cfg.configure_logging(args = args, ident = "irdbd")

        startup_msg = self.cfg.get("startup-message", "")
        if startup_msg:
            logger.info(startup_msg)

        self.cfg.set_global_flags()

        self.db = MySQLdb.connect(user   = self.cfg.get("sql-username"),
                                  db     = self.cfg.get("sql-database"),
                                  passwd = self.cfg.get("sql-password"))

        self.cur = self.db.cursor()
        self.db.autocommit(True)

        self.bpki_ta         = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta"))
        self.rpkid_cert      = rpki.x509.X509(Auto_update = self.cfg.get("rpkid-cert"))
        self.irdbd_cert      = rpki.x509.X509(Auto_update = self.cfg.get("irdbd-cert"))
        self.irdbd_key       = rpki.x509.RSA( Auto_update = self.cfg.get("irdbd-key"))

        u = urlparse.urlparse(self.cfg.get("http-url"))

        assert u.scheme in ("", "http") and \
               u.username is None and \
               u.password is None and \
               u.params   == "" and \
               u.query    == "" and \
               u.fragment == ""

        rpki.http_simple.server(host         = u.hostname or "localhost",
                                port         = u.port or 443,
                                handlers     = ((u.path, self.handler),))