1#!/bin/sh 2# Copyright (C) 2010, 2012 Internet Systems Consortium, Inc. ("ISC") 3# 4# Permission to use, copy, modify, and/or distribute this software for any 5# purpose with or without fee is hereby granted, provided that the above 6# copyright notice and this permission notice appear in all copies. 7# 8# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14# PERFORMANCE OF THIS SOFTWARE. 15# 16# Generate a DNS RR from an x.509 certificate 17# Currently only supports TLSA, but can be extended to support 18# other DANE types such as SMIMEA in the future. 19# 20# Requires: openssl 21 22USAGE="$BASENAME [options] <filename> 23Options: 24 -f <input format>: PEM | DLR 25 -n <name>: record name (default: _443._tcp) 26 -o <origin>: zone origin (default: none; name will be relative) 27 -m <matching type>: NONE (0) | SHA256 (1) | SHA512 (2) 28 -r <RR type>: TLSA 29 -s <selector>: FULL (0) | PK (1) 30 -t <ttl>: TTL of the TLSA record (default: none) 31 -u <certificate usage>: CA (0) | SERVICE (1) | TA (2) | DOMAIN (3)" 32 33NM="_443._tcp" 34CU=2 35SELECTOR=0 36MTYPE=1 37IN= 38FORM=PEM 39TTL= 40RRTYPE=TLSA 41BASENAME=`basename $0`; 42 43while getopts "xn:o:u:s:t:m:i:f:r:" c; do 44 case $c in 45 x) set -x; DEBUG=-x;; 46 m) MTYPE="$OPTARG";; 47 n) NM="$OPTARG";; 48 o) ORIGIN="$OPTARG";; 49 r) RRTYPE="$OPTARG";; 50 s) SELECTOR="$OPTARG";; 51 t) TTL="$OPTARG";; 52 u) CU="$OPTARG";; 53 *) echo "$USAGE" 1>&2; exit 1;; 54 esac 55done 56shift `expr $OPTIND - 1 || true` 57 58if test "$#" -eq 1; then 59 IN=$1 60else 61 echo "$USAGE" 1>&2; exit 1 62fi 63 64ORIGIN=`echo $ORIGIN | sed 's/\([^.]$\)/\1./'` 65if [ -n "$ORIGIN" ]; then 66 NM=`echo $NM | sed 's/\.$//'` 67 NM="$NM.$ORIGIN" 68fi 69 70case "$CU" in 71 [Cc][Aa]) CU=0;; 72 [Ss][Ee][Rr][Vv]*) CU=1;; 73 [Tt][Aa]) CU=2;; 74 [Dd][Oo][Mm]*) CU=3;; 75 [0123]) ;; 76 *) echo "bad certificate usage -u \"$CU\"" 1>&2; exit 1;; 77esac 78 79case "$SELECTOR" in 80 [Ff][Uu][Ll][Ll]) SELECTOR=0;; 81 [Pp][Kk]) SELECTOR=1;; 82 [01]) ;; 83 *) echo "bad selector -s \"$SELECTOR\"" 1>&2; exit 1;; 84esac 85 86case "$MTYPE" in 87 0|[Nn][Oo][Nn][Ee]) HASH='od -A n -v -t xC';; 88 1|[Ss][Hh][Aa]256) HASH='openssl dgst -sha256';; 89 2|[Ss][Hh][Aa]512) HASH='openssl dgst -sha512';; 90 *) echo "bad matching type -m \"$MTYPE\"" 1>&2; exit 1;; 91esac 92 93case "$FORM" in 94 [Pp][Ee][Mm]) FORM=PEM;; 95 [Dd][Ll][Rr]) FORM=DLR;; 96 *) echo "bad input file format -f \"$FORM\"" 1>&2; exit 1 97esac 98 99case "$RRTYPE" in 100 [Tt][Ll][Ss][Aa]) RRTYPE=TLSA;; 101 *) echo "invalid RR type" 1>&2; exit 1 102esac 103 104if test -z "$IN" -o ! -s "$IN"; then 105 echo "bad input file -i \"$IN\"" 1>&2; exit 1 106fi 107 108echo "; $BASENAME -o$NM -u$CU -s$SELECTOR -m$MTYPE -f$FORM $IN" 109 110(if test "$SELECTOR" = 0; then 111 openssl x509 -in "$IN" -inform "$FORM" -outform DER 112else 113 openssl x509 -in "$IN" -inform "$FORM" -noout -pubkey \ 114 | sed -e '/PUBLIC KEY/d' \ 115 | openssl base64 -d 116fi) \ 117 | $HASH \ 118 | awk ' 119 # format Association Data as in Appendix C of the DANE RFC 120 BEGIN { 121 print "'"$NM\t\t$TTL\tIN TLSA\t$CU $SELECTOR $MTYPE"' ("; 122 leader = "\t\t\t\t\t"; 123 } 124 /.+/ { 125 gsub(/ +/, "", $0); 126 buf = buf $0; 127 while (length(buf) >= 36) { 128 print leader substr(buf, 1, 36); 129 buf = substr(buf, 37); 130 } 131 } 132 END { 133 if (length(buf) > 34) 134 print leader buf "\n" leader ")"; 135 else 136 print leader buf " )"; 137 }' 138