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 1880 2008-06-12 21:54:53Z sra $
00009
00010 Copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN")
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 ARIN DISCLAIMS ALL WARRANTIES WITH
00017 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00018 AND FITNESS. IN NO EVENT SHALL ARIN 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
00025 import sys, os, time, getopt, urlparse, traceback
00026 import tlslite.api, MySQLdb, lxml.etree
00027 import rpki.https, rpki.config, rpki.resource_set, rpki.relaxng
00028 import rpki.exceptions, rpki.left_right, rpki.log, rpki.x509
00029
00030 def handler(query, path):
00031 try:
00032
00033 db.ping()
00034
00035 q_msg = rpki.left_right.cms_msg.unwrap(query, (bpki_ta, rpkid_cert))
00036
00037 if not isinstance(q_msg, rpki.left_right.msg) or q_msg.type != "query":
00038 raise rpki.exceptions.BadQuery, "Unexpected %s PDU" % repr(q_msg)
00039
00040 r_msg = rpki.left_right.msg()
00041 r_msg.type = "reply"
00042
00043 for q_pdu in q_msg:
00044
00045 try:
00046 if not isinstance(q_pdu, rpki.left_right.list_resources_elt):
00047 raise rpki.exceptions.BadQuery, "Unexpected %s PDU" % repr(q_pdu)
00048
00049 r_pdu = rpki.left_right.list_resources_elt()
00050 r_pdu.tag = q_pdu.tag
00051 r_pdu.self_id = q_pdu.self_id
00052 r_pdu.child_id = q_pdu.child_id
00053
00054 cur.execute("""SELECT registrant_id, subject_name, valid_until FROM registrant
00055 WHERE registrant.rpki_self_id = %s AND registrant.rpki_child_id = %s
00056 """, (q_pdu.self_id, q_pdu.child_id))
00057 if cur.rowcount != 1:
00058 raise rpki.exceptions.NotInDatabase, \
00059 "This query should have produced a single exact match, something's messed up (rowcount = %d, self_id = %s, child_id = %s)" \
00060 % (cur.rowcount, q_pdu.self_id, q_pdu.child_id)
00061
00062 registrant_id, subject_name, valid_until = cur.fetchone()
00063 r_pdu.subject_name = subject_name
00064 r_pdu.valid_until = valid_until.strftime("%Y-%m-%dT%H:%M:%SZ")
00065 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,))
00066 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,))
00067 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,))
00068
00069 except Exception, data:
00070 rpki.log.error(traceback.format_exc())
00071 r_pdu = rpki.left_right.report_error_elt.from_exception(data, q_pdu.self_id)
00072
00073 r_msg.append(r_pdu)
00074
00075 return 200, rpki.left_right.cms_msg.wrap(r_msg, irdbd_key, irdbd_cert)
00076
00077 except Exception, data:
00078 rpki.log.error(traceback.format_exc())
00079
00080
00081
00082
00083 return 500, "Unhandled exception %s: %s" % (data.__class__.__name__, data)
00084
00085 os.environ["TZ"] = "UTC"
00086 time.tzset()
00087
00088 rpki.log.init("irdbd")
00089
00090 cfg_file = "irdbd.conf"
00091
00092 opts,argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"])
00093 for o,a in opts:
00094 if o in ("-h", "--help", "-?"):
00095 print __doc__
00096 sys.exit(0)
00097 if o in ("-c", "--config"):
00098 cfg_file = a
00099 if argv:
00100 raise RuntimeError, "Unexpected arguments %s" % argv
00101
00102 cfg = rpki.config.parser(cfg_file, "irdbd")
00103
00104 startup_msg = cfg.get("startup-message", "")
00105 if startup_msg:
00106 rpki.log.info(startup_msg)
00107
00108 db = MySQLdb.connect(user = cfg.get("sql-username"),
00109 db = cfg.get("sql-database"),
00110 passwd = cfg.get("sql-password"))
00111
00112 cur = db.cursor()
00113
00114 bpki_ta = rpki.x509.X509(Auto_file = cfg.get("bpki-ta"))
00115 rpkid_cert = rpki.x509.X509(Auto_file = cfg.get("rpkid-cert"))
00116 irdbd_cert = rpki.x509.X509(Auto_file = cfg.get("irdbd-cert"))
00117 irdbd_key = rpki.x509.RSA( Auto_file = cfg.get("irdbd-key"))
00118
00119 u = urlparse.urlparse(cfg.get("https-url"))
00120
00121 assert u.scheme in ("", "https") and \
00122 u.username is None and \
00123 u.password is None and \
00124 u.params == "" and \
00125 u.query == "" and \
00126 u.fragment == ""
00127
00128 rpki.https.server(server_key = irdbd_key,
00129 server_cert = irdbd_cert,
00130 client_ta = (bpki_ta, rpkid_cert),
00131 host = u.hostname or "localhost",
00132 port = u.port or 443,
00133 handlers = ((u.path, handler),))