From fef075f317533013664d9b890e3a7705b674b8dc Mon Sep 17 00:00:00 2001 From: B Stack Date: Mon, 10 Sep 2018 10:15:33 -0400 Subject: add OPENSSL_BIN and OPENSSL_CONF options these will support the subjectAltName extension coming soon Please enter the commit message for your changes. Lines starting --- .gitignore | 1 + files/certreq.sh | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index fee9217..7eace93 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.conf +.*.swp diff --git a/files/certreq.sh b/files/certreq.sh index 5a21205..132c049 100755 --- a/files/certreq.sh +++ b/files/certreq.sh @@ -13,6 +13,7 @@ # 2018-06-19 Fix get number of ca cert # 2018-07-30 add error checking on the request and authorization # 2018-08-16 update error checking and exit codes +# 2018-09-10 add CERTREQ_OPENSSL_BIN and CERTREQ_OPENSSL_CONF values # Usage: in ansible role certreq # Microsoft CA cert templates have permissions on them. A user must be able to "enroll" on the template. # Reference: ftemplate.sh 2017-10-10x; framework.sh 2017-10-09a @@ -36,6 +37,8 @@ version ${certreqversion} --ca CA hostname or base URL. Example: ca2.example.com --reqid Request ID. Needed by --fetch action. --no-ca Skip downloading the CA cert chain. + --openssl-bin Use this binary for openssl. Default is "openssl" + --openssl-conf Use this config for openssl. Default is none. ACTIONS: --list list available templates and exit. --csr filename Provide a .csr file instead of making a new csr. Accepts "stdin" to read from standard in. @@ -59,7 +62,7 @@ ENDUSAGE # DEFINE FUNCTIONS openssl_req() { - # call: openssl_req "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" + # call: openssl_req "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_openssl_config}" # outputs: # vars: ${CSR} ${DATA} ${CERTATTRIB} # files: ${CERTREQ_WORKDIR}/${this_filename}.crt ${CERTREQ_WORKDIR}/${thisfilename}.key @@ -69,6 +72,8 @@ openssl_req() { local this_subject="${2}" local this_action="${3}" local this_csr="${4}" + local this_openssl_bin="${5}" + local this_openssl_config="${6}" debuglev 8 && echo "Action ${this_action}" case "${this_action}" in @@ -88,7 +93,7 @@ openssl_req() { esac ;; *) - openssl req -new -nodes \ + "${this_openssl_bin}" req ${this_openssl_config} -new -nodes \ -out "${CERTREQ_WORKDIR}/${this_filename}.csr" \ -keyout "${CERTREQ_WORKDIR}/${this_filename}.key" \ -subj "${this_subject}" @@ -246,18 +251,18 @@ get_latest_ca_cert_chain() { -H 'Content-Type: application/x-www-form-urlencoded' )" # CONVERT TO PEM - echo "${CURRENT_P7B}" | openssl pkcs7 -print_certs -out "${CERTREQ_TEMPFILE}" + echo "${CURRENT_P7B}" | "${CERTREQ_OPENSSL_BIN}" pkcs7 -print_certs -out "${CERTREQ_TEMPFILE}" # RENAME TO PROPER FILENAME # will read only the first cert, so get domain of issuer of it. - CA_DOMAIN="$( openssl x509 -in "${CERTREQ_TEMPFILE}" -noout -issuer 2>/dev/null | sed -r -e 's/^.*CN=[A-Za-z0-9]+\.//;' )" + CA_DOMAIN="$( "${CERTREQ_OPENSSL_BIN}" x509 -in "${CERTREQ_TEMPFILE}" -noout -issuer 2>/dev/null | sed -r -e 's/^.*CN=[A-Za-z0-9]+\.//;' )" CHAIN_FILE="chain-${CA_DOMAIN}.crt" mv -f "${CERTREQ_TEMPFILE}" "${CERTREQ_WORKDIR}/${CHAIN_FILE}" 1>/dev/null 2>&1 } action_get_cert() { - # call: action_get_cert "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" + # call: action_get_cert "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_config_string}" # outputs: # vars: ${curloutput} # files: ${CHAIN_FILE} ${CERTREQ_CNPARAM}.crt and .key and @@ -270,9 +275,11 @@ action_get_cert() { local this_ca_host="${5}" local this_action="${6}" local this_csr="${7}" + local this_openssl_bin="${8}" + local this_openssl_config="${9}" # GENERATE PRIVATE KEY - openssl_req "${this_cnparam}" "${this_subject}" "${this_action}" "${this_csr}" + openssl_req "${this_cnparam}" "${this_subject}" "${this_action}" "${this_csr}" "${this_openssl_bin}" "${this_openssl_config}" debuglev 8 && { echo "CSR=${CSR}" echo "DATA=${DATA}" @@ -315,7 +322,7 @@ action_get_cert() { } action_request() { - # call: action_request "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" + # call: action_request "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_openssl_config}" debuglev 9 && ferror "$FUNCNAME $@" local this_cnparam="${1}" @@ -325,9 +332,11 @@ action_request() { local this_ca_host="${5}" local this_action="${6}" local this_csr="${7}" + local this_openssl_bin="${8}" + local this_openssl_config="${9}" # GENERATE PRIVATE KEY - openssl_req "${this_cnparam}" "${this_subject}" "${this_action}" "${this_csr}" + openssl_req "${this_cnparam}" "${this_subject}" "${this_action}" "${this_csr}" "${this_openssl_bin}" "${this_openssl_config}" debuglev 8 && { echo "CSR=${CSR}" echo "DATA=${DATA}" @@ -453,6 +462,8 @@ parseFlag() { "request" | "request-only" ) CERTREQ_ACTION="request";; "no-ca" | "noca" ) CERTREQ_SKIP_CACERTS=1;; "req" | "reqid" | "req-id" | "request" | "requestid" | "request-id" ) getval; CERTREQ_REQID="${tempval}";; + "openssl-bin" | "openssl" | "opensslbin" | "openssl-binary" | "opensslexec" | "openssl-exec" ) getval; CERTREQ_OPENSSL_BIN="${tempval}";; + "openssl-conf" | "opensslconf" | "openssl_conf" ) getval; CERTREQ_OPENSSL_CONF="${tempval}";; esac debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}"; } @@ -546,6 +557,8 @@ define_if_new CERTREQ_CLEANUP_SEC 300 logfile="$( TMPDIR="${CERTREQ_WORKDIR}" mktemp -t tmp.XXXXXXXXXX )" CERTREQ_TEMPFILE="$( TMPDIR="${CERTREQ_WORKDIR}" mktemp -t tmp.XXXXXXXXXX )" define_if_new CERTREQ_ACTION "generate" +define_if_new CERTREQ_OPENSSL_BIN "openssl" +# no CERTREQ_OPENSSL_CONF defined by default. Just use the system default unless specified. # calculate the subject if test -n "${CERTREQ_CNPARAM}"; @@ -573,6 +586,12 @@ define_if_new CERTREQ_CA "http://ca2.ad.example.com" # generate cahost CERTREQ_CAHOST="$( echo "${CERTREQ_CA}" | sed -r -e 's/https?:\/\///g' -e 's/(\.[a-z]{2,3})\/$/\1/;' )" +# calculate openssl_conf string if necessary +if test -n "${CERTREQ_OPENSSL_CONF}" ; +then + CERTREQ_openssl_config="-config ${CERTREQ_OPENSSL_CONF}" +fi + ## REACT TO BEING A CRONJOB #if test ${is_cronjob} -eq 1; #then @@ -611,7 +630,7 @@ debuglev 5 && { request) # alias of "request-only" - action_request "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" + action_request "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_openssl_config}" ;; fetch) @@ -622,14 +641,14 @@ debuglev 5 && { *) # default action="generate" # also catches "generate-csr" - action_get_cert "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" + action_get_cert "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_openssl_config}" ;; esac # CHECK EVERYTHING failed=0 # start out with everything worked - openssloutput="$( openssl x509 -in "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" -noout -subject -issuer -startdate -enddate 2>/dev/null )" + openssloutput="$( "${CERTREQ_OPENSSL_BIN}" x509 -in "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" -noout -subject -issuer -startdate -enddate 2>/dev/null )" # 1 interaction with website failed: invalid login credentials or curl returned non-zero value if echo "${MESSAGE}" | grep -qiE 'unauthorized' || test ${curloutput} -ne 0 ; -- cgit From 3c9701eb14d3cd97224dcfe92ba070e29482c292 Mon Sep 17 00:00:00 2001 From: B Stack Date: Mon, 10 Sep 2018 13:38:54 -0400 Subject: add subjectAltName support add --dnssans and --ipsans flags and CERTREQ_DNSSANS and CERTREQ_IPSANS environment variables --- files/certreq.sh | 138 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/files/certreq.sh b/files/certreq.sh index 132c049..e1638d4 100755 --- a/files/certreq.sh +++ b/files/certreq.sh @@ -6,25 +6,26 @@ # Title: Script that Requests a Certificate from a Microsoft Sub-CA # Purpose: Automate host certificate generation in a domain environment # Package: ansible role certreq -# History: +# History: # 2017-11-22 Add ca cert chain # 2018-04-16 Add --list and --csr options # 2018-05-07 Add actions for using a CA with manually-approved certs # 2018-06-19 Fix get number of ca cert # 2018-07-30 add error checking on the request and authorization # 2018-08-16 update error checking and exit codes -# 2018-09-10 add CERTREQ_OPENSSL_BIN and CERTREQ_OPENSSL_CONF values +# 2018-09-10 add CERTREQ_OPENSSL_BIN and CERTREQ_OPENSSL_CONF values, and SAN support # Usage: in ansible role certreq # Microsoft CA cert templates have permissions on them. A user must be able to "enroll" on the template. # Reference: ftemplate.sh 2017-10-10x; framework.sh 2017-10-09a # fundamental curl statements https://stackoverflow.com/questions/31283476/submitting-base64-csr-to-a-microsoft-ca-via-curl/39722983#39722983 +# subjectaltname in openssl.cnf https://bgstack15.wordpress.com/2017/05/21/generate-certificate-with-subjectaltname-attributes-in-freeipa/ # Improve: fiversion="2017-10-10x" -certreqversion="2018-08-16a" +certreqversion="2018-09-10b" usage() { less -F >&2 <] [-l|-g] [--list|--csr /path/to/file|--fetch|--request] [--no-ca] [--reqid ] +usage: certreq.sh [-dhV] [-u username] [-p password] [-w tempdir] [-t template] [--cn CN] [--ca ] [-l|-g] [--list|--csr /path/to/file|--fetch|--request] [--no-ca] [--reqid ] [--openssl-bin /bin/openssl] [--openssl-conf /opt/openssl.cnf] version ${certreqversion} -d debug Show debugging info, including parsed variables. -h usage Show this usage block. @@ -39,6 +40,8 @@ version ${certreqversion} --no-ca Skip downloading the CA cert chain. --openssl-bin Use this binary for openssl. Default is "openssl" --openssl-conf Use this config for openssl. Default is none. + --dnssans Use a pipe-delimited set of values as subjectAltName dns entries. + --ipsans Use a pipe-delimited set of values as subjectAltName ip entries. ACTIONS: --list list available templates and exit. --csr filename Provide a .csr file instead of making a new csr. Accepts "stdin" to read from standard in. @@ -74,7 +77,7 @@ openssl_req() { local this_csr="${4}" local this_openssl_bin="${5}" local this_openssl_config="${6}" - + debuglev 8 && echo "Action ${this_action}" case "${this_action}" in *-csr) @@ -150,7 +153,7 @@ submit_csr() { -H "Referer: ${this_ca}/certsrv/certrqxt.asp" \ -H 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko' \ -H 'Content-Type: application/x-www-form-urlencoded' \ - --data "Mode=newreq&CertRequest=${this_cert}&CertAttrib=${this_cert_attrib}&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=" )" + --data "Mode=newreq&CertRequest=${this_cert}&CertAttrib=${this_cert_attrib}&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=" )" OUTPUTLINK="$( echo "${FULLPAGE}" | grep -A 1 'function handleGetCert() {' | tail -n 1 | cut -d '"' -f 2 )" CERTLINK="${this_ca}/certsrv/${OUTPUTLINK}" ;; @@ -265,7 +268,7 @@ action_get_cert() { # call: action_get_cert "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_config_string}" # outputs: # vars: ${curloutput} - # files: ${CHAIN_FILE} ${CERTREQ_CNPARAM}.crt and .key and + # files: ${CHAIN_FILE} ${CERTREQ_CNPARAM}.crt and .key and debuglev 9 && ferror "$FUNCNAME $@" local this_cnparam="${1}" @@ -284,9 +287,9 @@ action_get_cert() { echo "CSR=${CSR}" echo "DATA=${DATA}" echo "CERTATTRIB=${CERTATTRIB}" - } + } - # SUBMIT CERTIFICATE SIGNING REQUEST + # SUBMIT CERTIFICATE SIGNING REQUEST submit_csr "${this_user_string}" "${this_ca}" "${this_ca_host}" "${CSR}" "${CERTATTRIB}" "${this_action}" debuglev 8 && { echo "FULLPAGE=${FULLPAGE}" @@ -341,9 +344,9 @@ action_request() { echo "CSR=${CSR}" echo "DATA=${DATA}" echo "CERTATTRIB=${CERTATTRIB}" - } + } - # SUBMIT CERTIFICATE SIGNING REQUEST + # SUBMIT CERTIFICATE SIGNING REQUEST submit_csr "${this_user_string}" "${this_ca}" "${this_ca_host}" "${CSR}" "${CERTATTRIB}" "${this_action}" debuglev 8 && { echo "FULLPAGE=${FULLPAGE}" @@ -352,7 +355,7 @@ action_request() { echo "DISPOSITION=${DISPOSITION}" echo "MESSAGE=${MESSAGE}" } - + } action_fetch() { @@ -393,7 +396,7 @@ action_fetch() { action_list_templates() { # call: action_list_templates "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" debuglev 9 && ferror "$FUNCNAME $@" - + local this_user_string="${1}" local this_ca="${2}" local this_ca_host="${3}" @@ -413,6 +416,15 @@ action_list_templates() { } +file_section_has_value() { + # call: file_section_has_value "${thisfile}" "${sectionregex}" "${nextsectionregex}" "${valueregex}" + ___fshv_file="${1}" + ___fshv_sectionregex="${2}" + ___fshv_nextsectionregex="${3}" + ___fshv_valueregex="${4}" + test -n "$( sed -n -r -e "/${___fshv_sectionregex}/,/${___fshv_nextsectionregex}/p" "${___fshv_file}" 2>/dev/null | grep -q -r -e "${___fshv_valueregex}" )" +} + # DEFINE TRAPS clean_certreq() { @@ -464,8 +476,10 @@ parseFlag() { "req" | "reqid" | "req-id" | "request" | "requestid" | "request-id" ) getval; CERTREQ_REQID="${tempval}";; "openssl-bin" | "openssl" | "opensslbin" | "openssl-binary" | "opensslexec" | "openssl-exec" ) getval; CERTREQ_OPENSSL_BIN="${tempval}";; "openssl-conf" | "opensslconf" | "openssl_conf" ) getval; CERTREQ_OPENSSL_CONF="${tempval}";; + "dnssans" | "dns-sans" | "dnssan" | "dns-san" ) getval; CERTREQ_DNSSANS="${tempval}";; + "ipsans" | "ip-sans" | "ipsan" | "ip-san" ) getval; CERTREQ_IPSANS="${tempval}";; esac - + debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}"; } } @@ -558,7 +572,9 @@ logfile="$( TMPDIR="${CERTREQ_WORKDIR}" mktemp -t tmp.XXXXXXXXXX )" CERTREQ_TEMPFILE="$( TMPDIR="${CERTREQ_WORKDIR}" mktemp -t tmp.XXXXXXXXXX )" define_if_new CERTREQ_ACTION "generate" define_if_new CERTREQ_OPENSSL_BIN "openssl" -# no CERTREQ_OPENSSL_CONF defined by default. Just use the system default unless specified. +# no default CERTREQ_OPENSSL_CONF. Just use system default. +# no default CERTREQ_DNSSANS, which is pipe-delimited. +# no default CERTREQ_IPSANS, which is pipe-delimited. # calculate the subject if test -n "${CERTREQ_CNPARAM}"; @@ -586,10 +602,13 @@ define_if_new CERTREQ_CA "http://ca2.ad.example.com" # generate cahost CERTREQ_CAHOST="$( echo "${CERTREQ_CA}" | sed -r -e 's/https?:\/\///g' -e 's/(\.[a-z]{2,3})\/$/\1/;' )" -# calculate openssl_conf string if necessary +# verify openssl_conf dependency if test -n "${CERTREQ_OPENSSL_CONF}" ; then - CERTREQ_openssl_config="-config ${CERTREQ_OPENSSL_CONF}" + if ! test -r "${CERTREQ_OPENSSL_CONF}" ; + then + ferror "${scriptfile}: 1004. CERTREQ_OPENSSL_CONF file ${CERTREQ_OPENSSL_CONF} is invalid or not found. Aborted." && exit 1004 + fi fi ## REACT TO BEING A CRONJOB @@ -605,6 +624,87 @@ fi #trap "CTRLZ" 18 trap "clean_certreq" 0 +# PREPARE CUSTOM CONF FILE WITH ANY SUBJECTALTNAME ENTRIES +if test -n "${CERTREQ_DNSSANS}${CERTREQ_IPSANS}" ; +then + + # initialize new conf file + CERTREQ_openssl_conf_new="$( TMPDIR="${CERTREQ_WORKDIR}" mktemp -t openssl.cnf.XXXXXXXXXX )" + + # select conf file + if test -z "${CERTREQ_OPENSSL_CONF}" ; + then + # need to calculate the default conf file + CERTREQ_first_found="$( find /etc/pki/tls/openssl.cnf /usr/local/ssl/openssl.cnf 2>/dev/null | head -n1 )" + if ! test -r "${CERTREQ_first_found}" ; + then + ferror "${scriptfile}: 1004. Cannot determine default openssl.cnf for inserting SANs. Aborted." && exit 1004 + else + CERTREQ_OPENSSL_CONF="${CERTREQ_first_found}" && unset CERTREQ_first_found + fi + fi + + # copy in contents + /bin/cp -p "${CERTREQ_OPENSSL_CONF}" "${CERTREQ_openssl_conf_new}" + CERTREQ_OPENSSL_CONF="${CERTREQ_openssl_conf_new}" && unset CERTREQ_openssl_conf_new + + # make modifications, add v3_req + #if test -z "$( sed -n -r -e '/^\s*\[ req \]/,/^\s*\[/p' "${CERTREQ_OPENSSL_CONF}" 2>/dev/null | grep -r -e '^\s*req_extensions' )" ; + if ! file_section_has_value "${CERTREQ_OPENSSL_CONF}" "^\s*\[ req \]" "^\s*\[" "^\s*req_extensions" ; + then + # need to add req_extensions = v3_req to [ req ] + # get line number of [ req ] + CERTREQ_line_num="$( awk '/^\s*\[ req \]/{print FNR}' "${CERTREQ_OPENSSL_CONF}" 2>/dev/null )" + if test -z "${CERTREQ_line_num}" ; + then + # no line containing + echo "[ req ]" >> "${CERTREQ_OPENSSL_CONF}" + CERTREQ_line_num="$( wc -l < "${CERTREQ_OPENSSL_CONF}" )" + fi + sed -i -r -e "${CERTREQ_line_num}areq_extensions = v3_req" "${CERTREQ_OPENSSL_CONF}" + fi + + # make modifications, add SAN to [ v3_req ] + #if test -z "$( sed -n -r -e '/^\s*\[ v3_req \]/,/^\s*\[/p' "${CERTREQ_OPENSSL_CONF}" 2>/dev/null | grep + if ! file_section_has_value "${CERTREQ_OPENSSL_CONF}" "^\s*\[ v3_req \]" "^\s*\[" "^\s*subjectAltName" ; + then + # need to add it + CERTREQ_line_num="$( awk '/^\s*\[ v3_req \]/{print FNR}' "${CERTREQ_OPENSSL_CONF}" 2>/dev/null )" + if test -z "${CERTREQ_line_num}" ; + then + # need to add the section too + echo "[ v3_req ]" >> "${CERTREQ_OPENSSL_CONF}" + CERTREQ_line_num="$( wc -l < "${CERTREQ_OPENSSL_CONF}" )" + fi + sed -i -r -e "${CERTREQ_line_num}asubjectAltName = @alt_names" "${CERTREQ_OPENSSL_CONF}" + fi + + # make modifications, add subject alt names section + # start by preparing the exact string to make + CERTREQ_san_lines="$( test -n "${CERTREQ_DNSSANS}" && echo "${CERTREQ_DNSSANS}" | tr '|' '\n' | awk 'BEGIN{a=0} {a=a+1 ; print "DNS."a" = "$0 ;}' ; test -n "${CERTREQ_IPSANS}" && echo "${CERTREQ_IPSANS}" | tr '|' '\n' | awk 'BEGIN{a=0} {a=a+1 ; print "IP."a" = "$0 ;}')" + # add to file + if ! file_section_has_value "${CERTREQ_OPENSSL_CONF}" "^\s*\[alt_names\]" "^\s*\[" "=" ; + then + # need to add the values + CERTREQ_line_num="$( awk '/^\s*\[alt_names\]/{print FNR}' "${CERTREQ_OPENSSL_CONF}" 2>/dev/null )" + if test -z "${CERTREQ_line_num}" ; + then + # need to add the section too + echo "[alt_names]" >> "${CERTREQ_OPENSSL_CONF}" + CERTREQ_line_num="$( wc -l < "${CERTREQ_OPENSSL_CONF}" )" + fi + echo "${CERTREQ_san_lines}" | while read line ; do sed -i -r -e "${CERTREQ_line_num}a${line}" "${CERTREQ_OPENSSL_CONF}" ; CERTREQ_line_num=$(( CERTREQ_line_num + 1 )) ; done + fi + + # clean up + unset CERTREQ_line_num +fi + +if test -n "${CERTREQ_OPENSSL_CONF}" ; +then + CERTREQ_openssl_config="-config ${CERTREQ_OPENSSL_CONF}" +fi + # DEBUG SIMPLECONF debuglev 5 && { ferror "Using values" @@ -627,7 +727,7 @@ debuglev 5 && { list) action_list_templates "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" ;; - + request) # alias of "request-only" action_request "${CERTREQ_CNPARAM}" "${CERTREQ_SUBJECT}" "${CERTREQ_USER}:${CERTREQ_PASS}" "${CERTREQ_CA}" "${CERTREQ_CAHOST}" "${CERTREQ_ACTION}" "${CERTREQ_CSR}" "${CERTREQ_OPENSSL_BIN}" "${CERTREQ_openssl_config}" @@ -680,6 +780,7 @@ case "${CERTREQ_ACTION}" in request) echo "workdir: ${CERTREQ_WORKDIR}" echo "logfile: ${logfile}" + test -n "${CERTREQ_OPENSSL_CONF}" && echo "openssl_conf: ${CERTREQ_OPENSSL_CONF}" echo "csr: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.csr" echo "key: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.key" echo "reqid: ${REQUESTID}" @@ -699,6 +800,7 @@ case "${CERTREQ_ACTION}" in # for generate and generate-csr and everything else really echo "workdir: ${CERTREQ_WORKDIR}" echo "logfile: ${logfile}" + test -n "${CERTREQ_OPENSSL_CONF}" && echo "openssl_conf: ${CERTREQ_OPENSSL_CONF}" echo "csr: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.csr" echo "certificate: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" echo "key: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.key" -- cgit