X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=utilities%2Fovs-pki.in;h=501b06e47bce40bcb1bee84e6a4de66af0b76b46;hb=HEAD;hp=22b5f2a0c8a72c398becb39508921be0b581badd;hpb=496d0fe53648c34b1fbcce008314c6bbf1582ee2;p=sliver-openvswitch.git diff --git a/utilities/ovs-pki.in b/utilities/ovs-pki.in index 22b5f2a0c..501b06e47 100755 --- a/utilities/ovs-pki.in +++ b/utilities/ovs-pki.in @@ -1,6 +1,6 @@ #! /bin/sh -# Copyright (c) 2008, 2009 Nicira Networks, Inc. +# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,6 +24,38 @@ batch=no log='@LOGDIR@/ovs-pki.log' keytype=rsa bits=2048 + +# OS-specific compatibility routines +case $(uname -s) in +FreeBSD|NetBSD) + file_mod_epoch() + { + stat -r "$1" | awk '{print $10}' + } + + file_mod_date() + { + stat -f '%Sm' "$1" + } + + sha1sum() + { + sha1 "$@" + } + ;; +*) + file_mod_epoch() + { + date -r "$1" +%s + } + + file_mod_date() + { + date -r "$1" + } + ;; +esac + for option; do # This option-parsing mechanism borrowed from a Autoconf-generated # configure script under the following license: @@ -63,20 +95,6 @@ The valid stand-alone commands and their arguments are: fingerprint FILE Prints the fingerprint for FILE self-sign NAME Sign NAME-req.pem with NAME-privkey.pem, producing self-signed certificate NAME-cert.pem - -The following additional commands manage an online PKI: - ls [PREFIX] [TYPE] Lists incoming requests of the given TYPE, optionally - limited to those whose fingerprint begins with PREFIX - flush [TYPE] Rejects all incoming requests of the given TYPE - reject PREFIX [TYPE] Rejects the incoming request(s) whose fingerprint begins - with PREFIX and has the given TYPE - approve PREFIX [TYPE] Approves the incoming request whose fingerprint begins - with PREFIX and has the given TYPE - expire [AGE] Rejects all incoming requests older than AGE, in - one of the forms Ns, Nmin, Nh, Nday (default: 1day) - prompt [TYPE] Interactively prompts to accept or reject each incoming - request of the given TYPE - Each TYPE above is a certificate type: 'switch' (default) or 'controller'. Options for 'init', 'req', and 'req+sign' only: @@ -85,7 +103,7 @@ Options for 'init', 'req', and 'req+sign' only: this has an effect only on 'init'. -D, --dsaparam=FILE File with DSA parameters (DSA only) (default: dsaparam.pem within PKI directory) -Options for use with the 'sign' and 'approve' commands: +Options for use with the 'sign' command: -b, --batch Skip fingerprint verification Options that apply to any command: -d, --dir=DIR Directory where the PKI is located @@ -93,9 +111,14 @@ Options that apply to any command: -f, --force Continue even if file or directory already exists -l, --log=FILE Log openssl output to FILE (default: ovs-log.log) -h, --help Print this usage message. + -V, --version Display version information. EOF exit 0 ;; + -V|--version) + echo "ovs-pki (Open vSwitch) @VERSION@" + exit 0 + ;; --di*=*) pkidir=$optarg ;; @@ -161,11 +184,11 @@ if test -z "$command"; then exit 1 fi if test "$keytype" != rsa && test "$keytype" != dsa; then - echo "$0: argument to -k or --key must be rsa or dsa" + echo "$0: argument to -k or --key must be rsa or dsa" >&2 exit 1 fi if test "$bits" -lt 1024; then - echo "$0: argument to -B or --bits must be at least 1024" + echo "$0: argument to -B or --bits must be at least 1024" >&2 exit 1 fi if test -z "$dsaparam"; then @@ -173,9 +196,18 @@ if test -z "$dsaparam"; then fi case $log in /*) ;; - *) $log="$PWD/$log" ;; + *) log=`pwd`/$log ;; esac +logdir=$(dirname "$log") +if test ! -d "$logdir"; then + mkdir -p -m755 "$logdir" 2>/dev/null || true + if test ! -d "$logdir"; then + echo "$0: log directory $logdir does not exist and cannot be created" >&2 + exit 1 + fi +fi + if test "$command" = "init"; then if test -e "$pkidir" && test "$force" != "yes"; then echo "$0: $pkidir already exists and --force not specified" >&2 @@ -199,13 +231,12 @@ if test "$command" = "init"; then # Create the CAs. for ca in controllerca switchca; do echo "Creating $ca..." >&2 - oldpwd=$PWD + oldpwd=`pwd` mkdir -p $ca cd $ca mkdir -p certs crl newcerts mkdir -p -m 0700 private - mkdir -p -m 0733 incoming touch index.txt test -e crlnumber || echo 01 > crlnumber test -e serial || echo 01 > serial @@ -241,7 +272,7 @@ certificate = $dir/cacert.pem # The CA cert serial = $dir/serial # serial no file private_key = $dir/private/cakey.pem# CA private key RANDFILE = $dir/private/.rand # random number file -default_days = 365 # how long to certify for +default_days = 3650 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = md5 # md to use policy = policy # default policy @@ -249,6 +280,7 @@ email_in_dn = no # Don't add the email into cert DN name_opt = ca_default # Subject name display option cert_opt = ca_default # Certificate display option copy_extensions = none # Don't copy extensions from request +unique_subject = no # Allow certs with duplicate subjects # For the CA policy [ policy ] @@ -271,7 +303,7 @@ EOF -newkey $newkey -keyout private/cakey.pem -out careq.pem \ 1>&3 2>&3 openssl ca -config ca.cnf -create_serial -out cacert.pem \ - -days 1095 -batch -keyfile private/cakey.pem -selfsign \ + -days 3650 -batch -keyfile private/cakey.pem -selfsign \ -infiles careq.pem 1>&3 2>&3 chmod 0700 private/cakey.pem @@ -287,13 +319,6 @@ one_arg() { fi } -zero_or_one_args() { - if test -n "$arg2"; then - echo "$0: $command must have zero or one arguments; use --help for help" >&2 - exit 1 - fi -} - one_or_two_args() { if test -z "$arg1"; then echo "$0: $command must have one or two arguments; use --help for help" >&2 @@ -308,38 +333,6 @@ must_not_exist() { fi } -resolve_prefix() { - test -n "$type" || exit 123 # Forgot to call check_type? - - case $1 in - ????*) - ;; - *) - echo "Prefix $arg1 is too short (less than 4 hex digits)" - exit 0 - ;; - esac - - fingerprint=$(cd "$pkidir/${type}ca/incoming" && echo "$1"*-req.pem | sed 's/-req\.pem$//') - case $fingerprint in - "${1}*") - echo "No certificate requests matching $1" - exit 1 - ;; - *" "*) - echo "$1 matches more than one certificate request:" - echo $fingerprint | sed 's/ /\ -/g' - exit 1 - ;; - *) - # Nothing to do. - ;; - esac - req="$pkidir/${type}ca/incoming/$fingerprint-req.pem" - cert="$pkidir/${type}ca/certs/$fingerprint-cert.pem" -} - make_tmpdir() { TMP=/tmp/ovs-pki.tmp$$ rm -rf $TMP @@ -348,11 +341,10 @@ make_tmpdir() { } fingerprint() { - local file=$1 - local name=${1-$2} - local date=$(date -r $file) - local fingerprint - if grep -q -e '-BEGIN CERTIFICATE-' "$file"; then + file=$1 + name=${1-$2} + date=$(file_mod_date "$file") + if grep -e '-BEGIN CERTIFICATE-' "$file" > /dev/null; then fingerprint=$(openssl x509 -noout -in "$file" -fingerprint | sed 's/SHA1 Fingerprint=//' | tr -d ':') else @@ -437,6 +429,8 @@ make_request() { must_not_exist "$arg1-privkey.pem" must_not_exist "$arg1-req.pem" make_tmpdir + # Use uuidgen or date to create unique subject DNs. + unique=`(uuidgen) 2>/dev/null` || unique=`date +"%Y %b %d %T"` cat > "$TMP/req.cnf" <&3 2>&3 \ + || exit $? else must_exist "$dsaparam" - newkey=dsa:$dsaparam + (umask 077 && openssl gendsa -out "$1-privkey.pem" "$dsaparam") \ + 1>&3 2>&3 || exit $? fi - openssl req -config "$TMP/req.cnf" -text -nodes \ - -newkey $newkey -keyout "$1-privkey.pem" -out "$1-req.pem" 1>&3 2>&3 + openssl req -config "$TMP/req.cnf" -new -text \ + -key "$1-privkey.pem" -out "$1-req.pem" 1>&3 2>&3 } sign_request() { @@ -472,7 +468,7 @@ sign_request() { } glob() { - local files=$(echo $1) + files=$(echo $1) if test "$files" != "$1"; then echo "$files" fi @@ -515,84 +511,14 @@ elif test "$command" = self-sign; then must_exist "$arg1-privkey.pem" must_not_exist "$arg1-cert.pem" - openssl x509 -in "$arg1-req.pem" -out "$arg1-cert.pem" \ - -signkey "$arg1-privkey.pem" -req -text 2>&3 -elif test "$command" = ls; then - check_type "$arg2" - - cd "$pkidir/${type}ca/incoming" - for file in $(glob "$arg1*-req.pem"); do - fingerprint $file - done -elif test "$command" = flush; then - check_type "$arg1" - - rm -f "$pkidir/${type}ca/incoming/"* -elif test "$command" = reject; then - one_or_two_args - check_type "$arg2" - resolve_prefix "$arg1" - - rm -f "$req" -elif test "$command" = approve; then - one_or_two_args - check_type "$arg2" - resolve_prefix "$arg1" - - make_tmpdir - cp "$req" "$TMP/$req" - verify_fingerprint "$TMP/$req" - sign_request "$TMP/$req" - rm -f "$req" "$TMP/$req" -elif test "$command" = prompt; then - zero_or_one_args - check_type "$arg1" - - make_tmpdir - cd "$pkidir/${type}ca/incoming" - for req in $(glob "*-req.pem"); do - cp "$req" "$TMP/$req" - - cert=$(echo "$pkidir/${type}ca/certs/$req" | - sed 's/-req.pem/-cert.pem/') - if test -f $cert; then - echo "Request $req already approved--dropping duplicate request" - rm -f "$req" "$TMP/$req" - continue - fi + # Create both the private key and certificate with restricted permissions. + (umask 077 && \ + openssl x509 -in "$arg1-req.pem" -out "$arg1-cert.pem.tmp" \ + -signkey "$arg1-privkey.pem" -req -days 3650 -text) 2>&3 || exit $? - echo - echo - fingerprint "$TMP/$req" "$req" - printf "Disposition for this request (skip/approve/reject)? " - read answer - case $answer in - approve) - echo "Approving $req" - sign_request "$TMP/$req" "$cert" - rm -f "$req" "$TMP/$req" - ;; - r*) - echo "Rejecting $req" - rm -f "$req" "$TMP/$req" - ;; - *) - echo "Skipping $req" - ;; - esac - done -elif test "$command" = expire; then - zero_or_one_args - cutoff=$(($(date +%s) - $(parse_age ${arg1-1day}))) - for type in switch controller; do - cd "$pkidir/${type}ca/incoming" || exit 1 - for file in $(glob "*"); do - time=$(date -r "$file" +%s) - if test "$time" -lt "$cutoff"; then - rm -f "$file" - fi - done - done + # Reset the permissions on the certificate to the user's default. + cat "$arg1-cert.pem.tmp" > "$arg1-cert.pem" + rm -f "$arg1-cert.pem.tmp" else echo "$0: $command command unknown; use --help for help" >&2 exit 1