00001 """ 00002 Cross-certification tool to issue a new certificate based on an old 00003 one that was issued by somebody else. The point of the exercise is to 00004 end up with a valid certificate in our own BPKI which has the same 00005 subject name and subject public key as the one we're replacing. 00006 00007 Usage: python cross_certify.py { -i | --in } input_cert 00008 { -c | --ca } issuing_cert 00009 { -k | --key } issuing_cert_key 00010 { -s | --serial } serial_filename 00011 [ { -h | --help } ] 00012 [ { -o | --out } filename (default: stdout) ] 00013 [ { -l | --lifetime } timedelta (default: 30 days) ] 00014 00015 $Id: cross_certify.py 2553 2009-06-30 05:13:12Z sra $ 00016 00017 Copyright (C) 2009 Internet Systems Consortium ("ISC") 00018 00019 Permission to use, copy, modify, and distribute this software for any 00020 purpose with or without fee is hereby granted, provided that the above 00021 copyright notice and this permission notice appear in all copies. 00022 00023 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 00024 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00025 AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 00026 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00027 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00028 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00029 PERFORMANCE OF THIS SOFTWARE. 00030 00031 Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") 00032 00033 Permission to use, copy, modify, and distribute this software for any 00034 purpose with or without fee is hereby granted, provided that the above 00035 copyright notice and this permission notice appear in all copies. 00036 00037 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH 00038 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00039 AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, 00040 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00041 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00042 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00043 PERFORMANCE OF THIS SOFTWARE. 00044 """ 00045 00046 import os, time, getopt, sys, POW, rpki.x509, rpki.sundial 00047 00048 os.environ["TZ"] = "UTC" 00049 time.tzset() 00050 00051 def usage(errmsg = None): 00052 if errmsg is None: 00053 sys.stdout.write(__doc__) 00054 sys.exit(0) 00055 else: 00056 sys.stderr.write(errmsg + "\n" + __doc__) 00057 sys.exit(1) 00058 00059 child = None 00060 parent = None 00061 keypair = None 00062 serial_file = None 00063 lifetime = rpki.sundial.timedelta(days = 30) 00064 output = None 00065 00066 opts, argv = getopt.getopt(sys.argv[1:], "h?i:o:c:k:s:l:", 00067 ["help", "in=", "out=", "ca=", 00068 "key=", "serial=", "lifetime="]) 00069 for o, a in opts: 00070 if o in ("-h", "--help", "-?"): 00071 usage() 00072 elif o in ("-i", "--in"): 00073 child = rpki.x509.X509(Auto_file = a) 00074 elif o in ("-o", "--out"): 00075 output = a 00076 elif o in ("-c", "--ca"): 00077 parent = rpki.x509.X509(Auto_file = a) 00078 elif o in ("-k", "--key"): 00079 keypair = rpki.x509.RSA(Auto_file = a) 00080 elif o in ("-s", "--serial"): 00081 serial_file = a 00082 elif o in ("-l", "--lifetime"): 00083 lifetime = rpki.sundial.timedelta.parse(a) 00084 00085 if argv: 00086 usage("Unused arguments: %r" % argv) 00087 elif child is None: 00088 usage("--in not specified") 00089 elif parent is None: 00090 usage("--ca not specified") 00091 elif keypair is None: 00092 usage("--key not specified") 00093 elif serial_file is None: 00094 usage("--serial not specified") 00095 00096 now = rpki.sundial.now() 00097 notAfter = now + lifetime 00098 00099 try: 00100 f = open(serial_file, "r") 00101 serial = f.read() 00102 f.close() 00103 serial = int(serial.splitlines()[0], 16) 00104 except IOError: 00105 serial = 1 00106 00107 cert = parent.cross_certify(keypair, child, serial, notAfter, now) 00108 00109 f = open(serial_file, "w") 00110 f.write("%02x\n" % (serial + 1)) 00111 f.close() 00112 00113 if output is None: 00114 print cert.get_PEM() 00115 else: 00116 f = open(output, "w") 00117 f.write(cert.get_PEM()) 00118 f.close() 00119