aboutsummaryrefslogtreecommitdiff
path: root/openssl/trunk/ssl/s2_lib.c
AgeCommit message (Collapse)Author
2006-06-20Pulling OpenSSL 0.9.8b into trunkRob Austein
svn path=/openssl/trunk; revision=3
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
#!/usr/bin/env python

# $Id$
#
# Copyright (C) 2014  Dragon Research Labs ("DRL")
# Portions copyright (C) 2009-2013  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 notices and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND DRL AND ISC DISCLAIM ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL DRL OR
# 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.

import os
import glob
import shutil
import sqlite3
import rpki.rtr.client
import rpki.rtr.channels

def find_free_name(fmt, n = 10):
  """
  Handle SKI hash collisions by allowing a small number of distinct
  filenames for each ASN/SKI pair.
  """

  for i in xrange(n):
    fn = fmt % i
    if not os.path.exists(fn):
      return fn
  raise RuntimeError("Couldn't find a free filename for key %s after %d tries" % (fmt, n))

class ClientChannel(rpki.rtr.client.ClientChannel):
  """
  Subclass ClientChannel to extend .end_of_data() method.
  """

  def end_of_data(self, version, serial, nonce, refresh, retry, expire):
    """
    Call base method to do all the normal EndOfData processing, then
    dump out the key database using the symlink-to-directory hack so
    we can rename() the result to perform an atomic installation.
    """

    # Run the base method
    super(ClientChannel, self).end_of_data(version, serial, nonce, refresh, retry, expire)

    # Set up our new output directory
    dn = "%s.%s" % (self.args.bgpsec_key_directory, rpki.rtr.channels.Timestamp.now())
    ln = "%s.%s" % (self.args.bgpsec_key_directory, ".tmp")
    if os.path.exists(ln):
      os.unlink(ln)
    os.makedirs(dn)

    # Write all the keys
    for asn, gski, key in self.sql.execute("SELECT asn, ski, key FROM routerkey"):
      with open(find_free_name("%s/%s.%s.%%d.key" % (dn, asn, gski)), "wb") as f:
        f.write(key.decode("base64"))

    # Install the new directory
    os.symlink(os.path.basename(dn), ln)
    os.rename(ln, self.args.bgpsec_key_directory)

    # Clean up old output directories
    pattern = ".[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z"
    for gn in glob.iglob(self.args.bgpsec_key_directory + pattern):
      if gn != dn:
        shutil.rmtree(gn)

def SymlinkToDirectory(path):
  """
  argparse "type" function to clean up and sanity check --bgpsec-key-directory.
  """

  path = os.path.abspath(path).rstrip("/")
  if os.path.exists(path) and not os.path.islink(path):
    raise ValueError
  return path

# Grab handle on the normal client argparse setup function
client_argparse_setup = rpki.rtr.client.argparse_setup

# Extend argparse setup to add our own (required) parameter
def argparse_setup(subparsers):
  subparser = client_argparse_setup(subparsers)
  subparser.add_argument("--bgpsec-key-directory", required = True, type = SymlinkToDirectory,
                         help = "where to write BGPSEC router keys")
  return subparser

# Splice our extensions into client
rpki.rtr.client.argparse_setup = argparse_setup
rpki.rtr.client.ClientChannelClass = ClientChannel

# And run the program
import rpki.rtr.main
rpki.rtr.main.main()