#!/usr/bin/env bash # Define test functions. # See numerous configuration variables later on in this file that you can set # in the environment or the site.sh file. The definitions in the site.sh file # override # # Create working dir as variable "dir" # The functions are somewhat wildgrown, a little too many: # - expectpart # - expecteof # - expecteof_netconf # - expecteofx # - expecteofeq # - expecteof_file # - expectwait # - expectmatch #set -e # : ${A=B} vs : ${A:=B} # colon also checks for NULL # Testfile (not including path) : ${testfile:=$(basename $0)} # SKIPLIST lists the filenames of the test files that you do *not* want to run. # The format is a whitespace separated list of filenames. Specify the SKIPLIST # either in the shell environment or in the site.sh file. Any SKIPLIST specified # in site.sh overrides a SKIPLIST specified in the environment. If not specified # in either the environment or the site.sh, then the default SKIPLIST is empty. : ${SKIPLIST:=""} >&2 echo "Running $testfile" # Save stty STTYSETTINGS=$(stty -g) # Generated config file from autotools / configure if [ -f ./config.sh ]; then . ./config.sh if [ $? -ne 0 ]; then return -1 # error fi fi # Test number from start : ${testnr:=0} # Test number in this test testi=0 # Single test. Set by "new" testname= # Valgind memory leak check. # The values are: # 0: No valgrind check # 1: Start valgrind at every new testcase. Check result every next new # 2: Start valgrind every new backend start. Check when backend stops # 3: Start valgrind every new restconf start. Check when restconf stops # 4: Start valgrind every new snmp start. Check when snmp stops # : ${valgrindtest=0} # If set to 0, override starting of clixon_backend in test (you bring your own) : ${BE:=1} # If BE is set, some tests have a user timeout to show which params to set # for starting a backend : ${BETIMEOUT:=10} # If set, enable debugging (of backend and restconf daemons) : ${DBG:=0} # If set to 0, override starting of clixon_restconf in test (you bring your own) : ${RC:=1} # Where to log restconf. Some systems may not have syslog, # eg logging to a file: RCLOG="-l f/www-data/restconf.log" : ${RCLOG:=} # If set to 0, override starting of clixon_snmp in test (you bring your own) : ${SN:=1} # Namespace: netconf base BASENS='urn:ietf:params:xml:ns:netconf:base:1.0' # Namespace: Clixon config CONFNS='xmlns="http://clicon.org/config"' # Namespace: Clixon lib LIBNS='xmlns="http://clicon.org/lib"' # Namespace: Clixon restconf RESTCONFNS='xmlns="http://clicon.org/restconf"' # Default netconf namespace statement, typically as placed on top-level urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:base:1.1]]>]]>" # Minimal hello message that excludes 1.1 capability, in the case EOM style framing is needed HELLONO11="urn:ietf:params:netconf:base:1.0]]>]]>" # XXX cannot get this to work for all combinations of nc/netcat fcgi/native # But leave it here for debugging where netcat works properly if [ -n "$(type netcat 2> /dev/null)" ]; then netcat="netcat -w 1" # -N does not work on fcgi # nc on freebsd does not work either #elif [ -n "$(type nc 2> /dev/null)" ]; then # netcat=nc else netcat= fi # SSL serv cert common name XXX should use DNS resolve : ${SSLCN:="localhost"} # Options passed to curl calls # -s : silent # -S : show error # -i : Include HTTP response headers # -k : insecure : ${CURLOPTS:="-Ssik"} # Set HTTP version 1.1 or 2 if ${HAVE_LIBNGHTTP2}; then : ${HVER:=2} else : ${HVER:=1.1} fi if [ ${HVER} = 2 ]; then if ${HAVE_HTTP1}; then # This is if http/1 is enabled (unset proto=HTTP_2 in restconf_accept_client) CURLOPTS="${CURLOPTS} --http2" else # This is if http/1 is disabled (set proto=HTTP_2 in restconf_accept_client) CURLOPTS="${CURLOPTS} --http2-prior-knowledge" fi else CURLOPTS="${CURLOPTS} --http1.1" fi # Wait after daemons (backend/restconf) start. See mem.sh for valgrind if [ "$(uname -m)" = "armv7l" ]; then : ${DEMWAIT:=8} else : ${DEMWAIT:=2} fi # Multiplication factor to sleep less than whole seconds DEMSLEEP=0.2 # Some sleep implementations cannot handle sub-seconds, change to 1s sleep $DEMSLEEP || DEMSLEEP=1 # DEMWAIT is expressed in seconds, but really * DEMSLEEP let DEMLOOP=5*DEMWAIT # RESTCONF protocol, eg http or https if [ "${WITH_RESTCONF}" = "fcgi" ]; then : ${RCPROTO:=http} else : ${RCPROTO:=https} fi # www user (on linux typically www-data, freebsd www) # Start restconf user, can be root which is dropped to wwwuser : ${wwwstartuser:=root} # Some restconf tests can run IPv6, but its complicated because: # - docker by default does not run IPv6 : ${IPv6:=false} # Backend user BUSER=clicon # If set, unknown XML is treated as ANYDATA # This would only happen if you set option YANG_UNKNOWN_ANYDATA to something else than default : ${YANG_UNKNOWN_ANYDATA:=false} # Follow the binary programs that can be parametrized (eg with valgrind) : ${clixon_cli:=clixon_cli} : ${clixon_netconf:=clixon_netconf} : ${clixon_restconf:=clixon_restconf} : ${clixon_backend:=clixon_backend} : ${clixon_util_socket:=clixon_util_socket} : ${clixon_snmp:=clixon_snmp} : ${clixon_snmp_pidfile:="/var/tmp/clixon_snmp.pid"} : ${_ALREADY_HERE:=0} if [ -n "$CLICON_GROUP" ] && [ $_ALREADY_HERE -eq 0 ]; then # Extra test for some archs, ie ubuntu 18 that have problems with this sudo -g ${CLICON_GROUP} $clixon_netconf 2> /dev/null if [ $? -eq 0 ]; then clixon_cli="sudo -g ${CLICON_GROUP} $clixon_cli" clixon_netconf="sudo -g ${CLICON_GROUP} $clixon_netconf" clixon_restconf="sudo -g ${CLICON_GROUP} $clixon_restconf" clixon_snmp="sudo -g ${CLICON_GROUP} --preserve-env=MIBDIRS $clixon_snmp" clixon_util_socket="sudo -g ${CLICON_GROUP} $clixon_util_socket" fi fi _ALREADY_HERE=1 # Source the site-specific definitions for test script variables, if site.sh # exists. The variables defined in site.sh override any variables of the same # names in the environment in the current execution. if [ -f ./site.sh ]; then . ./site.sh if [ $? -ne 0 ]; then return -1 # skip fi # test skiplist. for f in $SKIPLIST; do if [ "$testfile" = "$f" ]; then echo "...skipped (see site.sh)" return -1 # skip fi done fi # Standard IETF RFC yang files. if [ -n "${YANG_STANDARD_DIR}" ]; then : ${IETFRFC=$YANG_STANDARD_DIR/ietf/RFC} fi : ${SNMPCHECK:=true} if $SNMPCHECK; then snmpget="$(type -p snmpget) -On -c public -v2c localhost " snmpbulkget="$(type -p snmpbulkget) -On -c public -v2c localhost " snmpset="$(type -p snmpset) -On -c public -v2c localhost " snmpgetstr="$(type -p snmpget) -c public -v2c localhost " snmpgetnext="$(type -p snmpgetnext) -On -c public -v2c localhost " snmpgetnextstr="$(type -p snmpgetnext) -c public -v2c localhost " if [ $valgrindtest -ne 0 ]; then # To avoid "Timeout: No Response from localhost" from netsnmp/snmpd set timeout to 10s snmptable="$(type -p snmptable) -c public -v2c localhost -t 10 " snmpwalk="$(type -p snmpwalk) -c public -v2c localhost -t 10 " else snmptable="$(type -p snmptable) -c public -v2c localhost " snmpwalk="$(type -p snmpwalk) -c public -v2c localhost " fi snmpwalkstr="$(type -p snmpwalk) -c public -v2c localhost " snmptranslate="$(type -p snmptranslate) " if [ "${ENABLE_NETSNMP}" == "yes" ]; then pgrep snmpd > /dev/null if [ $? != 0 ]; then echo -e "\e[31m\nenable-netsnmp set but snmpd not running, start with:" echo "systemctl start snmpd" echo "" echo "snmpd must be configured to use a Unix socket for agent communication" echo "and have a rwcommunity configured, make sure the following lines are" echo "added to /etc/snmp/snmpd.conf:" echo "" echo " rwcommunity public localhost" echo " agentxsocket unix:/var/run/snmp.sock" echo " agentxperms 777 777" echo "" echo "If you don't rely on systemd you can configure the lines above" echo "and start snmpd manually with 'snmpd -Lo -p /var/run/snmpd.pid'." echo -e "\e[0m" exit -1 fi fi function validate_oid(){ oid=$1 oid2=$2 type=$3 value=$4 result=$5 name="$($snmptranslate $oid)" name2="$($snmptranslate $oid2)" if [[ $oid =~ ^([0-9]|\.)+$ ]]; then get=$snmpget getnext=$snmpgetnext else get=$snmpgetstr getnext=$snmpgetnextstr fi if [ $oid == $oid2 ]; then if [ -z "$result" ]; then result="$oid = $type: $value" fi new "Validating OID: $oid2 = $type: $value" expectpart "$($get $oid)" 0 "$result" else if [ -z "$result" ]; then result="$oid2 = $type: $value" fi new "Validating next OID: $oid2 = $type: $value" expectpart "$($getnext $oid)" 0 "$result" fi } fi # Check sanity between --with-restconf setting and if nginx is started by systemd or not # This check is optional because some installs, such as vagrant make a non-systemd/direct # start : ${NGINXCHECK:=false} # Sanity nginx running on systemd platforms if $NGINXCHECK; then if systemctl > /dev/null 2>&1 ; then # even if systemd exists, nginx may be started in other ways nginxactive=$(systemctl show nginx |grep ActiveState=active) if [ "${WITH_RESTCONF}" = "fcgi" ]; then if [ -z "$nginxactive" -a ! -f /var/run/nginx.pid ]; then echo -e "\e[31m\nwith-restconf=fcgi set but nginx not running, start with:" echo "systemctl start nginx" echo -e "\e[0m" exit -1 fi else if [ -n "$nginxactive" -o -f /var/run/nginx.pid ]; then echo -e "\e[31m\nwith-restconf=fcgi not set but nginx running, stop with:" echo "systemctl stop nginx" echo -e "\e[0m" exit -1 fi fi fi # systemctl fi # Temp directory where all tests write their data to dir=/var/tmp/$0 if [ ! -d $dir ]; then mkdir $dir fi # Default restconf configuration: IPv4 # Can be placed in clixon-config # Note that https clause assumes there exists certs and keys in /etc/ssl,... # Args: # 1: auth-type (one of none, client-cert, user) # 2: pretty (if true pretty-print restconf return values) # [3: proto: http or https] # [4: http_data: true or false] # Note feature http-data must be enabled # Note, if AUTH=none then FEATURE clixon-restconf:allow-auth-none must be enabled # Note if https, check if server cert/key exists, if not generate them function restconf_config() { AUTH=$1 PRETTY=$2 # Change this to fixed parameters if [ $# -gt 2 ]; then myproto=$3 else myproto=$RCPROTO fi if [ $# -gt 3 ]; then myhttpdata=$4 else myhttpdata=false fi echo -n "clixon-restconf:fcgi" if [ $myproto = http ]; then echo -n "true" if ${myhttpdata}; then echo -n "true" fi echo "$AUTH$PRETTY$DBGdefault
0.0.0.0
80false
" else certdir=$dir/certs if [ ! -f ${dir}/clixon-server-crt.pem ]; then certdir=$dir/certs test -d $certdir || mkdir $certdir srvcert=${certdir}/clixon-server-crt.pem srvkey=${certdir}/clixon-server-key.pem cacert=${certdir}/clixon-ca-crt.pem cakey=${certdir}/clixon-ca-key.pem cacerts $cakey $cacert servercerts $cakey $cacert $srvkey $srvcert fi echo -n "true" if ${myhttpdata}; then echo -n "true" fi echo "$AUTH$PRETTY${certdir}/clixon-server-crt.pem${certdir}/clixon-server-key.pem${certdir}/clixon-ca-crt.pem$DBGdefault
0.0.0.0
443true
" fi } # Default autocli configuration # Can be placed in clixon-config # Exclude all modules instead as defined by arg1 # Args: # 1: modname module name pattern to be included # 2: list-keyword # 3: treerefstate function autocli_config() { modname=$1 listkw=$2 state=$3 TMP=$(cat < false $listkw $state include $modname enable $modname EOF ) echo "${TMP}" } # Some tests may set owner of testdir to something strange and quit, need # to reset to me if [ ! -G $dir ]; then u=$(whoami) sudo chown $u:$u $dir fi # If you bring your own backend BE=0 (it is already started), the backend may # have created some files (eg unix socket) in $dir and therefore cannot # be deleted. # Same with RC=0 if [ $BE -ne 0 -a $RC -ne 0 ]; then rm -rf $dir/* fi # error and exit, # arg1: expected # arg2: errmsg[optional] # Assumes: $dir and $expect are set # see err1 function err(){ expect=$1 ret=$2 echo -e "\e[31m\nError in Test$testnr [$testname]:" if [ $# -gt 0 ]; then echo "Expected" echo "$1" echo fi if [ $# -gt 1 ]; then echo "Received: $2" fi echo -e "\e[0m" echo "Diff between Expected and Received:" diff <(echo "$ret"| od -t c) <(echo "$expect"| od -t c) exit -1 #$testnr } # Don't print diffs function err1(){ echo -e "\e[31m\nError in Test$testnr [$testname]:" if [ $# -gt 0 ]; then echo "Expected: $1" echo fi if [ $# -gt 1 ]; then echo "Received: $2" fi echo -e "\e[0m" exit -1 #$testnr } # Test is previous test had valgrind errors if so quit function checkvalgrind(){ if [ -f $valgrindfile ]; then res=$(cat $valgrindfile | grep -e "Invalid" |awk '{print $4}' | grep -v '^0$') if [ -n "$res" ]; then >&2 cat $valgrindfile sudo rm -f $valgrindfile exit -1 fi res=$(cat $valgrindfile | grep -e "reachable" -e "lost:"|awk '{print $4}' | grep -v '^0$') if [ -n "$res" ]; then >&2 cat $valgrindfile sudo rm -f $valgrindfile exit -1 fi sudo rm -f $valgrindfile fi } # Check if two RFC6242 NETCONF frames are equal # Since they use \n you cannot just use = function chunked_equal() { echo "1:$1" echo "2:$2" if [ "$1" == "$2" ]; then return 0 else return 255 fi } # Given a string, add RFC6242 chunked framing around it # Args: # 0: string function chunked_framing() { str=$1 length=$(echo -n "$str"|wc -c) printf "\n#%s\n%s\n##\n" ${length} "${str}" } # Start clixon_snmp function start_snmp(){ cfg=$1 rm -f ${clixon_snmp_pidfile} export MIBDIRS $clixon_snmp -f $cfg -D $DBG & if [ $? -ne 0 ]; then err fi } # Stop clixon_snmp and Valgrind if needed function stop_snmp(){ if [ $valgrindtest -eq 4 ]; then pkill -f clixon_snmp sleep 1 checkvalgrind else killall -q clixon_snmp fi rm -f ${clixon_snmp_pidfile} } # Start backend with all varargs. # If valgrindtest == 2, start valgrind function start_backend(){ if [ $valgrindtest -eq 2 ]; then # Start in background since daemon version creates two traces: parent, # child. If background then only the single relevant. sudo $clixon_backend -F -D $DBG $* & else sudo $clixon_backend -D $DBG $* fi if [ $? -ne 0 ]; then err fi } function stop_backend(){ sudo clixon_backend -z $* if [ $? -ne 0 ]; then err "kill backend" fi if [ $valgrindtest -eq 2 ]; then sleep 1 checkvalgrind fi # sudo pkill -f clixon_backend # extra ($BUSER?) } # Wait for restconf to stop sending 502 Bad Gateway function wait_backend(){ freq=$(chunked_framing "") reply=$(echo "$freq" | $clixon_netconf -q1ef $cfg) # freply=$(chunked_framing "") # chunked_equal "$reply" "$freply" let i=0; while [[ $reply != *"]]>]]>" | $clixon_netconf -qef $cfg 2> /dev/null) # echo "reply:$reply" let i++; # echo "wait_backend $i" if [ $i -ge $DEMLOOP ]; then err "backend timeout $DEMWAIT seconds" fi done } # Start restconf daemon # @see wait_restconf function start_restconf(){ local clixon_restconf_="${clixon_restconf#sudo -g * }" # Start in background # echo "sudo -u $wwwstartuser $clixon_restconf_ $RCLOG -D $DBG $*" sudo -u $wwwstartuser $clixon_restconf_ $RCLOG -D $DBG $* /dev/null & if [ $? -ne 0 ]; then err1 "expected 0" "$?" fi } # Stop restconf daemon before test function stop_restconf_pre(){ sudo pkill -f clixon_restconf } # Stop restconf daemon after test # Some problems with pkill: # 1) Dont use $clixon_restconf (dont work in valgrind) # 2) Dont use -u $WWWUSER since clixon_restconf may drop privileges. # 3) After fork, it seems to take some time before name is right function stop_restconf(){ sudo pkill -f clixon_restconf if [ $valgrindtest -eq 3 ]; then sleep 1 checkvalgrind fi } # Wait for restconf to stop sending 502 Bad Gateway # @see start_restconf # Reasons for not working: if you run native is nginx running? # @note assumes port=80 if RCPROTO=http and port=443 if RCPROTO=https # Args: # 1: (optional) override RCPROTO with http or https function wait_restconf(){ if [ $# = 1 ]; then myproto=$1 else myproto=${RCPROTO} fi # echo "curl $CURLOPTS -X GET $myproto://localhost/restconf" hdr=$(curl $CURLOPTS -X GET $myproto://localhost/restconf 2> /dev/null) stty $STTYSETTINGS >/dev/null # echo "hdr:\"$hdr\"" let i=0; while [[ "$hdr" != *"200"* ]]; do # echo "wait_restconf $i" if [ $i -ge $DEMLOOP ]; then err1 "restconf timeout $DEMWAIT seconds" fi sleep $DEMSLEEP # echo "curl $CURLOPTS -X GET $myproto://localhost/restconf" hdr=$(curl $CURLOPTS -X GET $myproto://localhost/restconf 2> /dev/null) # echo "hdr:\"$hdr\"" let i++; done if [ $valgrindtest -eq 3 ]; then sleep 2 # some problems with valgrind fi } # Wait for restconf to stop # @note assumes port=80 if RCPROTO=http and port=443 if RCPROTO=https # @see wait_restconf function wait_restconf_stopped(){ # echo "curl $CURLOPTS $* $RCPROTO://localhost/restconf" hdr=$(curl $CURLOPTS $* $RCPROTO://localhost/restconf 2> /dev/null) # echo "hdr:\"$hdr\"" let i=0; while [[ $hdr = *"200 OK"* ]]; do # echo "wait_restconf_stopped $i" if [ $i -ge $DEMLOOP ]; then err1 "restconf timeout $DEMWAIT seconds" fi sleep $DEMSLEEP hdr=$(curl $CURLOPTS $* $RCPROTO://localhost/restconf 2> /dev/null) # echo "hdr:\"$hdr\"" let i++; done if [ $valgrindtest -eq 3 ]; then sleep 2 # some problems with valgrind fi } # Use pidfile to check snmp started. pidfile is created after init in clixon_snmp function wait_snmp() { let i=0; while [ ! -f ${clixon_snmp_pidfile} ]; do if [ $i -ge $DEMLOOP ]; then err1 "snmp timeout $DEMWAIT seconds" fi sleep $DEMSLEEP let i++; done } # End of single test, final tests before normal exit of test # Note this is a single test started by new, not a total test suite # Unset common variables that may affect next test if run in sequence by # eg all.sh or mem.sh function endtest() { # Commented from now, it is unclear what destroys the tty, if something does the original # problem should be fixed at the origin. # stty $STTYSETTINGS >/dev/null if [ $valgrindtest -eq 1 ]; then checkvalgrind fi # Unset common variables. More specific should be unset at end of script unset RCPROTO unset HAVE_LIBNGHTTP2 unset HVER unset AUTOCLI unset CURLOPTS unset RESTCONFIG unset LOGDST unset fyang unset ret unset count unset nr unset format unset perfnr unset perfreq unset pid unset validatexml unset xpath unset clixon_util_datastore unset clixon_util_json unset clixon_util_xml unset clixon_util_path unset clixon_util_stream unset clixon_util_xpath unset clixon_util_xml unset clixon_util_xml_mod } # Increment test number and print a nice string function new(){ if [ $valgrindtest -eq 1 ]; then checkvalgrind fi testnr=`expr $testnr + 1` testi=`expr $testi + 1` testname=$1 >&2 echo "Test $testi($testnr) [$1]" } # End of complete test-suite, eg a test file, mem.sh function endsuite() { unset CURLOPTS } # Evaluate and return # Example: expectpart $(fn arg) 0 "my return" -- "foo" # - evaluated expression # - expected command return value (0 if OK) or list of values, eg "55 56" # - expected stdout outcome* # - the token "--not--" # - not expected stdout outcome* # Example: # expectpart "$(a-shell-cmd arg)" 0 'expected match 1' 'expected match 2' --not-- 'not expected 1' # @note need to escape \[\] function expectpart(){ r=$? ret=$1 retval=$2 expect=$3 # echo "r:$r" # echo "ret:\"$ret\"" # echo "retval:$retval" # echo "expect:\"$expect\"" if [ "$retval" -eq "$retval" 2> /dev/null ] ; then # single retval if [ $r != $retval ]; then echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:" echo -e "\e[0m:" exit -1 fi else # List of retvals found=0 for rv in $retval; do if [ $r == $rv ]; then found=1 fi done if [ $found -eq 0 ]; then echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:" echo -e "\e[0m:" exit -1 fi fi if [ -z "$ret" -a -z "$expect" ]; then return fi # Loop over all variable args expect strings (skip first two args) # note that "expect" var is never actually used # Then test positive for strings, if the token --not-- is detected, then test negative for the rest positive=true; let i=0; for exp in "$@"; do if [ $i -gt 1 ]; then if [ "$exp" == "--not--" ]; then positive=false; else # echo "echo \"$ret\" | grep --null -o \"$exp"\" match=$(echo "$ret" | grep --null -i -o "$exp") #-i ignore case XXX -EZo: -E cant handle {} r=$? if $positive; then if [ $r != 0 ]; then err "$exp" "$ret" fi else if [ $r == 0 ]; then err "not $exp" "$ret" fi fi fi fi let i++; done # if [[ "$ret" != "$expect" ]]; then # err "$expect" "$ret" # fi } # Pipe stdin to command # Arguments: # - Command # - expected command return value (0 if OK) XXX SHOULD SWITCH w next # - stdin input # - expected stdout outcome # - expected stderr outcome (can be null) # Use this if you want regex eg ^foo$ function expecteof(){ cmd=$1 retval=$2 input=$3 expect=$4 if [ $# -gt 4 ]; then errfile=$(mktemp) expecterr=$5 # Do while read stuff ret=$($cmd 2> $errfile < $dir/expectwaitresult ret="" sleep $wait | cat <(echo "$input1$inputenc") -| $cmd | while [ 1 ] ; do read -t 20 r # echo "r:<$r>" if [ -z "$r" ]; then sleep 1 continue fi # Append $r to $ret ret="$ret$r" # echo "ret:$ret" let i=0; positive=true; let ok=0 let fail=0 for exp in "$@"; do if [ $i -gt 4 ]; then # echo "i:$i" # echo "exp:$exp" if [ "$exp" == "--not--" ]; then positive=false; else match=$(echo "$ret" | grep --null -i -o "$exp") # match=$(echo "$ret" | grep -Eo "$exp"); r=$? if $positive; then if [ $r != 0 ]; then # echo "fail: $exp" let fail++ break fi else if [ $r == 0 ]; then # echo "fail: $exp" let fail++ break fi fi fi fi let i++; done # for exp # echo "fail:$fail" if [ $fail -eq 0 ]; then # echo ok echo ok > $dir/expectwaitresult # break exit 0 fi done # cat $dir/expectwaitresult if [ $(cat $dir/expectwaitresult) != "ok" ]; then err "ok" "$(cat $dir/expectwaitresult)" cat $dir/expectwaitresult exit -1 fi } function expectmatch(){ ret=$1 r=$2 expret=$3 expect=$4 # echo "ret:$ret" # echo "ret:$r" # echo "expret:$expret" # echo "expect:$expect" if [ $r != $expret ]; then echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:" echo -e "\e[0m:" exit -1 fi if [ -z "$ret" -a -z "$expect" ]; then echo > /dev/null else match=$(echo "$ret" | grep -Eo "$expect") if [ -z "$match" ]; then err "$expect" "$ret" fi if [ -n "$expect2" ]; then match=`echo "$ret" | grep --null -Eo "$expect2"` if [ -z "$match" ]; then err $expect "$ret" fi fi fi } # Create CA certs # Output variables set as filenames on entry, set as cert/keys on exit: # Vars: # 1: cakey filename # 2: cacert filename function cacerts() { if [ $# -ne 2 ]; then echo "cacerts function: Expected: cakey cacert" exit 1 fi local cakey=$1 local cacert=$2 tmpdir=$dir/tmpcertdir test -d $tmpdir || mkdir $tmpdir # 1. CA cat< $tmpdir/ca.cnf [ ca ] default_ca = CA_default [ CA_default ] serial = ca-serial crl = ca-crl.pem database = ca-database.txt name_opt = CA_default cert_opt = CA_default default_crl_days = 9999 default_md = md5 [ req ] default_bits = ${CERTKEYLEN} days = 1 distinguished_name = req_distinguished_name attributes = req_attributes prompt = no output_password = password [ req_distinguished_name ] C = SE L = Stockholm O = Clixon OU = clixon CN = ca emailAddress = olof@hagsand.se [ req_attributes ] challengePassword = test EOF # Generate CA cert openssl req -batch -new -x509 -days 1 -config $tmpdir/ca.cnf -keyout $cakey -out $cacert || err "Generate CA cert" rm -rf $tmpdir } # Create server certs # Output variables set as filenames on entry, set as cert/keys on exit: # Vars: # 1: cakey filename (input) # 2: cacert filename (input) # 3: srvkey filename (output) # 4: srvcert filename (output) function servercerts() { if [ $# -ne 4 ]; then echo "servercerts function: Expected: cakey cacert srvkey srvcert" exit 1 fi cakey=$1 cacert=$2 srvkey=$3 srvcert=$4 tmpdir=$dir/tmpcertdir test -d $tmpdir || mkdir $tmpdir cat< $tmpdir/srv.cnf [req] prompt = no distinguished_name = dn req_extensions = ext [dn] CN = ${SSLCN} # localhost emailAddress = olof@hagsand.se O = Clixon L = Stockholm C = SE [ext] subjectAltName = DNS:clicon.org EOF # Generate server key openssl genpkey -algorithm RSA -out $srvkey || err "Generate server key" # Generate CSR (signing request) openssl req -batch -new -config $tmpdir/srv.cnf -key $srvkey -out $tmpdir/srv_csr.pem || err "Generate signing request" # Sign server cert by CA openssl x509 -req -extfile $tmpdir/srv.cnf -days 1 -passin "pass:password" -in $tmpdir/srv_csr.pem -CA $cacert -CAkey $cakey -CAcreateserial -out $srvcert || err "Sign server cert" rm -rf $tmpdir }