Browse Source

Support issue cert from existing CSR (#276)

fix https://github.com/Neilpang/acme.sh/issues/212
neil 8 years ago
parent
commit
10afcaca2f
1 changed files with 172 additions and 18 deletions
  1. 172 18
      acme.sh

+ 172 - 18
acme.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 #!/usr/bin/env sh
 
 
-VER=2.4.3
+VER=2.4.4
 
 
 PROJECT_NAME="acme.sh"
 PROJECT_NAME="acme.sh"
 
 
@@ -463,6 +463,60 @@ _signcsr() {
   return $_ret
   return $_ret
 }
 }
 
 
+#_csrfile
+_readSubjectFromCSR() {
+  _csrfile="$1"
+  if [ -z "$_csrfile" ] ; then
+    _usage "_readSubjectFromCSR mycsr.csr"
+    return 1
+  fi
+  openssl req  -noout  -in  "$_csrfile"  -subject | _egrep_o "CN=.*" | cut -d = -f 2 |  cut -d / -f 1
+}
+
+#_csrfile
+#echo comma separated domain list
+_readSubjectAltNamesFromCSR() {
+  _csrfile="$1"
+  if [ -z "$_csrfile" ] ; then
+    _usage "_readSubjectAltNamesFromCSR mycsr.csr"
+    return 1
+  fi
+  
+  _csrsubj="$(_readSubjectFromCSR "$_csrfile")"
+  _debug _csrsubj "$_csrsubj"
+  
+  _dnsAltnames="$(openssl req  -noout -text  -in  "$_csrfile" | grep "^ *DNS:.*" | tr -d ' ')"
+  _debug _dnsAltnames "$_dnsAltnames"
+  
+  if _contains "$_dnsAltnames," "DNS:$_csrsubj," ; then
+    _debug "AltNames contains subject"
+    _dnsAltnames="$(echo "$_dnsAltnames," | sed "s/DNS:$_csrsubj,//g")"
+  else
+    _debug "AltNames doesn't contain subject"
+  fi
+  
+  echo "$_dnsAltnames" | sed "s/DNS://g"
+}
+
+#_csrfile 
+_readKeyLengthFromCSR() {
+  _csrfile="$1"
+  if [ -z "$_csrfile" ] ; then
+    _usage "_readAllDomainListFromCSR mycsr.csr"
+    return 1
+  fi
+  
+  _outcsr="$(openssl req  -noout -text  -in  "$_csrfile")"
+  if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey" ; then
+    _debug "ECC CSR"
+    echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
+  else
+    _debug "RSA CSR"
+    echo "$_outcsr" | _egrep_o "^ *Public-Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
+  fi
+}
+
+
 _ss() {
 _ss() {
   _port="$1"
   _port="$1"
   
   
@@ -1478,6 +1532,7 @@ _clearupwebbroot() {
 
 
 }
 }
 
 
+#webroot, domain domainlist  keylength 
 issue() {
 issue() {
   if [ -z "$2" ] ; then
   if [ -z "$2" ] ; then
     _usage "Usage: $PROJECT_ENTRY --issue  -d  a.com  -w /path/to/webroot/a.com/ "
     _usage "Usage: $PROJECT_ENTRY --issue  -d  a.com  -w /path/to/webroot/a.com/ "
@@ -1631,25 +1686,29 @@ issue() {
     Le_Keylength=""
     Le_Keylength=""
   fi
   fi
   
   
-  _key=$(_readdomainconf Le_Keylength)
-  _debug "Read key length:$_key"
-  if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ] ; then
-    if ! createDomainKey $Le_Domain $Le_Keylength ; then 
-      _err "Create domain key error."
+  
+  if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ] ; then
+    _info "Signing from existing CSR."
+  else
+    _key=$(_readdomainconf Le_Keylength)
+    _debug "Read key length:$_key"
+    if [ ! -f "$CERT_KEY_PATH" ] || [ "$Le_Keylength" != "$_key" ] ; then
+      if ! createDomainKey $Le_Domain $Le_Keylength ; then 
+        _err "Create domain key error."
+        _clearup
+        return 1
+      fi
+    fi
+
+    if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"   ; then
+      _err "Create CSR error."
       _clearup
       _clearup
       return 1
       return 1
     fi
     fi
   fi
   fi
-  
+
   _savedomainconf "Le_Keylength"    "$Le_Keylength"
   _savedomainconf "Le_Keylength"    "$Le_Keylength"
   
   
-
-  if ! _createcsr "$Le_Domain" "$Le_Alt" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"   ; then
-    _err "Create CSR error."
-    _clearup
-    return 1
-  fi
-
   vlist="$Le_Vlist"
   vlist="$Le_Vlist"
   # verify each domain
   # verify each domain
   _info "Verify each domain"
   _info "Verify each domain"
@@ -2169,6 +2228,82 @@ renewAll() {
 }
 }
 
 
 
 
+#csr webroot
+signcsr(){
+  _csrfile="$1"
+  _csrW="$2"
+  if [ -z "$_csrfile" ] || [ -z "$_csrW" ]; then
+    _usage "Usage: $PROJECT_ENTRY --signcsr  --csr mycsr.csr  -w /path/to/webroot/a.com/ "
+    return 1
+  fi
+
+  _initpath
+
+  _csrsubj=$(_readSubjectFromCSR "$_csrfile")
+  if [ "$?" != "0" ] || [ -z "$_csrsubj" ] ; then
+    _err "Can not read subject from csr: $_csrfile"
+    return 1
+  fi
+
+  _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
+  if [ "$?" != "0" ] ; then
+    _err "Can not read domain list from csr: $_csrfile"
+    return 1
+  fi
+  _debug "_csrdomainlist" "$_csrdomainlist"
+  
+  _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
+  if [ "$?" != "0" ] || [ -z "$_csrkeylength" ] ; then
+    _err "Can not read key length from csr: $_csrfile"
+    return 1
+  fi
+  
+  _initpath "$_csrsubj" "$_csrkeylength"
+  mkdir -p "$DOMAIN_PATH"
+  
+  _info "Copy csr to: $CSR_PATH"
+  cp "$_csrfile" "$CSR_PATH"
+  
+  issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength"
+  
+}
+
+showcsr() {
+ _csrfile="$1"
+  _csrd="$2"
+  if [ -z "$_csrfile" ] && [ -z "$_csrd" ]; then
+    _usage "Usage: $PROJECT_ENTRY --showcsr  --csr mycsr.csr"
+    return 1
+  fi
+
+  _initpath
+  
+  _csrsubj=$(_readSubjectFromCSR "$_csrfile")
+  if [ "$?" != "0" ] || [ -z "$_csrsubj" ] ; then
+    _err "Can not read subject from csr: $_csrfile"
+    return 1
+  fi
+  
+  _info "Subject=$_csrsubj"
+
+  _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
+  if [ "$?" != "0" ] ; then
+    _err "Can not read domain list from csr: $_csrfile"
+    return 1
+  fi
+  _debug "_csrdomainlist" "$_csrdomainlist"
+
+  _info "SubjectAltNames=$_csrdomainlist"
+
+
+  _csrkeylength=$(_readKeyLengthFromCSR "$_csrfile")
+  if [ "$?" != "0" ] || [ -z "$_csrkeylength" ] ; then
+    _err "Can not read key length from csr: $_csrfile"
+    return 1
+  fi
+  _info "KeyLength=$_csrkeylength"
+}
+
 list() {
 list() {
   _raw="$1"
   _raw="$1"
   _initpath
   _initpath
@@ -2741,13 +2876,15 @@ Commands:
   --version, -v            Show version info.
   --version, -v            Show version info.
   --install                Install $PROJECT_NAME to your system.
   --install                Install $PROJECT_NAME to your system.
   --uninstall              Uninstall $PROJECT_NAME, and uninstall the cron job.
   --uninstall              Uninstall $PROJECT_NAME, and uninstall the cron job.
-  --upgrade                Upgrade $PROJECT_NAME to the latest code from $PROJECT
+  --upgrade                Upgrade $PROJECT_NAME to the latest code from $PROJECT .
   --issue                  Issue a cert.
   --issue                  Issue a cert.
+  --signcsr                Issue a cert from an existing csr.
   --installcert            Install the issued cert to apache/nginx or any other server.
   --installcert            Install the issued cert to apache/nginx or any other server.
   --renew, -r              Renew a cert.
   --renew, -r              Renew a cert.
-  --renewAll               Renew all the certs
+  --renewAll               Renew all the certs.
   --revoke                 Revoke a cert.
   --revoke                 Revoke a cert.
-  --list                   List all the certs
+  --list                   List all the certs.
+  --showcsr                Show the content of a csr.
   --installcronjob         Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
   --installcronjob         Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
   --uninstallcronjob       Uninstall the cron job. The 'uninstall' command can do this automatically.
   --uninstallcronjob       Uninstall the cron job. The 'uninstall' command can do this automatically.
   --cron                   Run cron job to renew all the certs.
   --cron                   Run cron job to renew all the certs.
@@ -2796,6 +2933,7 @@ Parameters:
   --ca-bundle                       Specifices the path to the CA certificate bundle to verify api server's certificate.
   --ca-bundle                       Specifices the path to the CA certificate bundle to verify api server's certificate.
   --nocron                          Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
   --nocron                          Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
   --ecc                             Specifies to use the ECC cert. Valid for '--installcert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
   --ecc                             Specifies to use the ECC cert. Valid for '--installcert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
+  --csr                             Specifies the input csr.
   "
   "
 }
 }
 
 
@@ -2871,6 +3009,7 @@ _process() {
   _ca_bundle=""
   _ca_bundle=""
   _nocron=""
   _nocron=""
   _ecc=""
   _ecc=""
+  _csr=""
   while [ ${#} -gt 0 ] ; do
   while [ ${#} -gt 0 ] ; do
     case "${1}" in
     case "${1}" in
     
     
@@ -2894,6 +3033,12 @@ _process() {
     --issue)
     --issue)
         _CMD="issue"
         _CMD="issue"
         ;;
         ;;
+    --signcsr)
+        _CMD="signcsr"
+        ;;
+    --showcsr)
+        _CMD="showcsr"
+        ;;
     --installcert|-i)
     --installcert|-i)
         _CMD="installcert"
         _CMD="installcert"
         ;;
         ;;
@@ -3122,7 +3267,10 @@ _process() {
     --ecc)
     --ecc)
         _ecc="isEcc"
         _ecc="isEcc"
         ;;
         ;;
-
+    --csr)
+        _csr="$2"
+        shift
+        ;;
     *)
     *)
         _err "Unknown parameter : $1"
         _err "Unknown parameter : $1"
         return 1
         return 1
@@ -3143,6 +3291,12 @@ _process() {
     issue)
     issue)
       issue  "$_webroot"  "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath"
       issue  "$_webroot"  "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath"
       ;;
       ;;
+    signcsr)
+      signcsr "$_csr" "$_webroot"
+      ;;
+    showcsr)
+      showcsr "$_csr" "$_domain"
+      ;;
     installcert)
     installcert)
       installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
       installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
       ;;
       ;;