aboutsummaryrefslogtreecommitdiff
path: root/scripts/cross_certify.py
blob: c696923c06eb99234c25fdb9f4a8ba5ca6283d80 (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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# $Id$
# 
# Copyright (C) 2009-2011  Internet Systems Consortium ("ISC")
# 
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
# 
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS.  IN NO EVENT SHALL ISC 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.
# 
# 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 notice and this permission notice appear in all copies.
# 
# THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS.  IN NO EVENT SHALL 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.

"""
Cross-certification tool to issue a new certificate based on an old
one that was issued by somebody else.  The point of the exercise is to
end up with a valid certificate in our own BPKI which has the same
subject name and subject public key as the one we're replacing.

Usage: python cross_certify.py { -i | --in     } input_cert
                               { -c | --ca     } issuing_cert
                               { -k | --key    } issuing_cert_key
                               { -s | --serial } serial_filename
                               [ { -h | --help } ]
                               [ { -o | --out  }     filename  (default: stdout)  ]
                               [ { -l | --lifetime } timedelta (default: 30 days) ]

"""

import os, time, getopt, sys, rpki.x509, rpki.sundial

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

def usage(errmsg = None):
  if errmsg is None:
    sys.stdout.write(__doc__)
    sys.exit(0)
  else:
    sys.stderr.write(errmsg + "\n" + __doc__)
    sys.exit(1)

child           = None
parent          = None
keypair         = None
serial_file     = None
lifetime        = rpki.sundial.timedelta(days = 30)
output          = None

opts, argv = getopt.getopt(sys.argv[1:], "h?i:o:c:k:s:l:",
                           ["help", "in=", "out=", "ca=",
                            "key=", "serial=", "lifetime="])
for o, a in opts:
  if o in ("-h", "--help", "-?"):
    usage()
  elif o in ("-i", "--in"):
    child = rpki.x509.X509(Auto_file = a)
  elif o in ("-o", "--out"):
    output = a
  elif o in ("-c", "--ca"):
    parent = rpki.x509.X509(Auto_file = a)
  elif o in ("-k", "--key"):
    keypair = rpki.x509.RSA(Auto_file = a)
  elif o in ("-s", "--serial"):
    serial_file = a
  elif o in ("-l", "--lifetime"):
    lifetime = rpki.sundial.timedelta.parse(a)

if argv:
  usage("Unused arguments: %r" % argv)
elif child is None:
  usage("--in not specified")
elif parent is None:
  usage("--ca not specified")
elif keypair is None:
  usage("--key not specified")
elif serial_file is None:
  usage("--serial not specified")

now = rpki.sundial.now()
notAfter = now + lifetime

try:
  f = open(serial_file, "r")
  serial = f.read()
  f.close()
  serial = int(serial.splitlines()[0], 16)
except IOError:
  serial = 1

cert = parent.cross_certify(keypair, child, serial, notAfter, now)

f = open(serial_file, "w")
f.write("%02x\n" % (serial + 1))
f.close()

if output is None:
  print cert.get_PEM()
else:
  f = open(output, "w")
  f.write(cert.get_PEM())
  f.close()