00001 """
00002 IR database daemon.
00003
00004 Usage: python irdbd.py [ { -c | --config } configfile ] [ { -h | --help } ]
00005
00006 Default configuration file is irdbd.conf, override with --config option.
00007
00008 $Id: irdbd.py 2481 2009-06-01 05:07:46Z sra $
00009
00010 Copyright (C) 2009 Internet Systems Consortium ("ISC")
00011
00012 Permission to use, copy, modify, and distribute this software for any
00013 purpose with or without fee is hereby granted, provided that the above
00014 copyright notice and this permission notice appear in all copies.
00015
00016 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00017 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00018 AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00019 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00020 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00021 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00022 PERFORMANCE OF THIS SOFTWARE.
00023
00024 Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN")
00025
00026 Permission to use, copy, modify, and distribute this software for any
00027 purpose with or without fee is hereby granted, provided that the above
00028 copyright notice and this permission notice appear in all copies.
00029
00030 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
00031 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00032 AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
00033 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00034 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00035 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00036 PERFORMANCE OF THIS SOFTWARE.
00037 """
00038
00039 import sys, os, time, getopt, urlparse, traceback, MySQLdb
00040 import rpki.https, rpki.config, rpki.resource_set, rpki.relaxng
00041 import rpki.exceptions, rpki.left_right, rpki.log, rpki.x509
00042
00043 def handler(query, path, cb):
00044 try:
00045
00046 db.ping()
00047
00048 q_msg = rpki.left_right.cms_msg.unwrap(query, (bpki_ta, rpkid_cert))
00049
00050 if not isinstance(q_msg, rpki.left_right.msg) or q_msg.type != "query":
00051 raise rpki.exceptions.BadQuery, "Unexpected %s PDU" % repr(q_msg)
00052
00053 r_msg = rpki.left_right.msg()
00054 r_msg.type = "reply"
00055
00056 for q_pdu in q_msg:
00057
00058 try:
00059 if not isinstance(q_pdu, rpki.left_right.list_resources_elt):
00060 raise rpki.exceptions.BadQuery, "Unexpected %s PDU" % repr(q_pdu)
00061
00062 r_pdu = rpki.left_right.list_resources_elt()
00063 r_pdu.tag = q_pdu.tag
00064 r_pdu.self_id = q_pdu.self_id
00065 r_pdu.child_id = q_pdu.child_id
00066
00067 cur.execute(
00068 """
00069 SELECT registrant_id, subject_name, valid_until FROM registrant
00070 WHERE registrant.rpki_self_id = %s AND registrant.rpki_child_id = %s
00071 """,
00072 (q_pdu.self_id, q_pdu.child_id))
00073 if cur.rowcount != 1:
00074 raise rpki.exceptions.NotInDatabase, \
00075 "This query should have produced a single exact match, something's messed up (rowcount = %d, self_id = %s, child_id = %s)" \
00076 % (cur.rowcount, q_pdu.self_id, q_pdu.child_id)
00077
00078 registrant_id, subject_name, valid_until = cur.fetchone()
00079 r_pdu.subject_name = subject_name
00080 r_pdu.valid_until = valid_until.strftime("%Y-%m-%dT%H:%M:%SZ")
00081 r_pdu.asn = rpki.resource_set.resource_set_as.from_sql(cur, "SELECT start_as, end_as FROM asn WHERE registrant_id = %s", (registrant_id,))
00082 r_pdu.ipv4 = rpki.resource_set.resource_set_ipv4.from_sql(cur, "SELECT start_ip, end_ip FROM net WHERE registrant_id = %s AND version = 4", (registrant_id,))
00083 r_pdu.ipv6 = rpki.resource_set.resource_set_ipv6.from_sql(cur, "SELECT start_ip, end_ip FROM net WHERE registrant_id = %s AND version = 6", (registrant_id,))
00084
00085 except Exception, data:
00086 rpki.log.error(traceback.format_exc())
00087 r_pdu = rpki.left_right.report_error_elt.from_exception(data, q_pdu.self_id)
00088
00089 r_msg.append(r_pdu)
00090
00091 cb(200, rpki.left_right.cms_msg.wrap(r_msg, irdbd_key, irdbd_cert))
00092
00093 except (rpki.async.ExitNow, SystemExit):
00094 raise
00095
00096 except Exception, data:
00097 rpki.log.error(traceback.format_exc())
00098
00099
00100
00101
00102 cb(500, "Unhandled exception %s: %s" % (data.__class__.__name__, data))
00103
00104 os.environ["TZ"] = "UTC"
00105 time.tzset()
00106
00107 rpki.log.init("irdbd")
00108
00109 cfg_file = "irdbd.conf"
00110
00111 opts, argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"])
00112 for o, a in opts:
00113 if o in ("-h", "--help", "-?"):
00114 print __doc__
00115 sys.exit(0)
00116 if o in ("-c", "--config"):
00117 cfg_file = a
00118 if argv:
00119 raise RuntimeError, "Unexpected arguments %s" % argv
00120
00121 cfg = rpki.config.parser(cfg_file, "irdbd")
00122
00123 startup_msg = cfg.get("startup-message", "")
00124 if startup_msg:
00125 rpki.log.info(startup_msg)
00126
00127 db = MySQLdb.connect(user = cfg.get("sql-username"),
00128 db = cfg.get("sql-database"),
00129 passwd = cfg.get("sql-password"))
00130
00131 cur = db.cursor()
00132
00133 bpki_ta = rpki.x509.X509(Auto_file = cfg.get("bpki-ta"))
00134 rpkid_cert = rpki.x509.X509(Auto_file = cfg.get("rpkid-cert"))
00135 irdbd_cert = rpki.x509.X509(Auto_file = cfg.get("irdbd-cert"))
00136 irdbd_key = rpki.x509.RSA( Auto_file = cfg.get("irdbd-key"))
00137
00138 u = urlparse.urlparse(cfg.get("https-url"))
00139
00140 assert u.scheme in ("", "https") and \
00141 u.username is None and \
00142 u.password is None and \
00143 u.params == "" and \
00144 u.query == "" and \
00145 u.fragment == ""
00146
00147 rpki.https.server(server_key = irdbd_key,
00148 server_cert = irdbd_cert,
00149 client_ta = (bpki_ta, rpkid_cert),
00150 host = u.hostname or "localhost",
00151 port = u.port or 443,
00152 handlers = ((u.path, handler),))