From 9d725af60221519a8ac4cc976a0af49ff0be2e26 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 13 Feb 2017 23:29:37 +0800 Subject: [PATCH 01/13] support nginx mode --- README.md | 32 ++++++-- acme.sh | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 235 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f1c74806..edc4555c 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ https://github.com/Neilpang/acmetest - Webroot mode - Standalone mode - Apache mode +- Nginx mode - DNS mode - [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) @@ -215,8 +216,27 @@ acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +# 7. Use Nginx mode -# 7. Use DNS mode: +**(requires you to be root/sudoer, since it is required to interact with Nginx server)** + +If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. + +Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. + +Just set string "nginx" as the second argument. + +It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version. + +So, the config is not changed. + +``` +acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com +``` + +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert + +# 8. Use DNS mode: Support the `dns-01` challenge. @@ -247,7 +267,7 @@ acme.sh --renew -d example.com Ok, it's finished. -# 8. Automatic DNS API integration +# 9. Automatic DNS API integration If your DNS provider supports API access, we can use that API to automatically issue the certs. @@ -280,7 +300,7 @@ If your DNS provider is not on the supported list above, you can write your own For more details: [How to use DNS API](dnsapi) -# 9. Issue ECC certificates +# 10. Issue ECC certificates `Let's Encrypt` can now issue **ECDSA** certificates. @@ -311,7 +331,7 @@ Valid values are: 3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** -# 10. How to renew the issued certs +# 11. How to renew the issued certs No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. @@ -328,7 +348,7 @@ acme.sh --renew -d example.com --force --ecc ``` -# 11. How to upgrade `acme.sh` +# 12. How to upgrade `acme.sh` acme.sh is in constant development, so it's strongly recommended to use the latest code. @@ -353,7 +373,7 @@ acme.sh --upgrade --auto-upgrade 0 ``` -# 12. Issue a cert from an existing CSR +# 13. Issue a cert from an existing CSR https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR diff --git a/acme.sh b/acme.sh index f03501b4..612c2094 100755 --- a/acme.sh +++ b/acme.sh @@ -45,6 +45,8 @@ MODE_STATELESS="stateless" STATE_VERIFIED="verified_ok" +NGINX="nginx:" + BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" END_CSR="-----END CERTIFICATE REQUEST-----" @@ -2277,10 +2279,186 @@ Allow from all return 0 } +#find the real nginx conf file +#backup +#set the nginx conf +#returns the real nginx conf file +_setNginx() { + _d="$1" + _croot="$2" + _thumbpt="$3" + if ! _exists "nginx"; then + _err "nginx command is not found." + return 1 + fi + FOUND_REAL_NGINX_CONF="" + BACKUP_NGINX_CONF="" + _debug _croot "$_croot" + _start_f="$(echo "$_croot" | cut -d : -f 2)" + _debug _start_f "$_start_f" + if [ -z "$_start_f" ]; then + _debug "find start conf from nginx command" + if [ -z "$NGINX_CONF" ]; then + NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")" + _debug NGINX_CONF "$NGINX_CONF" + NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)" + _debug NGINX_CONF "$NGINX_CONF" + if [ ! -f "$NGINX_CONF" ]; then + _err "'$NGINX_CONF' doesn't exist." + NGINX_CONF="" + return 1 + fi + _debug "Found nginx conf file:$NGINX_CONF" + fi + _start_f="$NGINX_CONF" + fi + _info "Start detect nginx conf for $_d from:$_start_f" + if ! _checkConf "$_d" "$_start_f"; then + "Can not find conf file for domain $d" + return 1 + fi + _info "Found conf file: $FOUND_REAL_NGINX_CONF" + + mkdir -p "$DOMAIN_BACKUP_PATH" + _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf" + _debug _backup_conf "$_backup_conf" + BACKUP_NGINX_CONF="$_backup_conf" + _info "Backup $FOUND_REAL_NGINX_CONF to $_backup_conf" + if ! cp "$FOUND_REAL_NGINX_CONF" "$_backup_conf"; then + _err "backup error." + FOUND_REAL_NGINX_CONF="" + return 1 + fi + + _info "Check the nginx conf before setting up." + if ! _exec "nginx -t" >/dev/null; then + _exec_err + return 1 + fi + + _info "OK, Set up nginx config file" + _ln=$(grep -n "^ *server_name.* $_d" "$_backup_conf" | cut -d : -f 1 | tr -d "\n") + _debug "_ln" "$_ln" + + if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + _err "write nginx conf error, but don't worry, the file is restored to the original version." + return 1 + fi + + echo " +location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { + default_type text/plain; + return 200 \"\$1.$_thumbpt\"; +} +" >> "$FOUND_REAL_NGINX_CONF" + + _ln=$(_math $_ln + 1) + if ! sed -n "${_ln},99999p" "$_backup_conf" >> "$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + _err "write nginx conf error, but don't worry, the file is restored." + return 1 + fi + + _info "nginx conf is done, let's check it again." + if ! _exec "nginx -t" >/dev/null; then + _exec_err + _err "It seems that nginx conf was broken, let's restore." + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + return 1 + fi + + _info "Reload nginx" + if ! _exec "nginx -s reload" >/dev/null; then + _exec_err + _err "It seems that nginx reload error, let's restore." + cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + return 1 + fi + + return 0 +} + +#d , conf +_checkConf() { + _d="$1" + _c_file="$2" + _debug "Start _checkConf from:$_c_file" + if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then + _debug "wildcard" + for _w_f in $2; do + if _checkConf "$1" "$_w_f"; then + return 0 + fi + done + #not found + return 1 + elif [ -f "$2" ]; then + _debug "single" + if _isRealNginxConf "$1" "$2"; then + _debug "$2 is found." + FOUND_REAL_NGINX_CONF="$2" + return 0 + fi + if grep "^ *include *.*;" "$2" >/dev/null; then + _debug "Try include files" + for included in $(grep "^ *include *.*;" "$2"| sed "s/include //" | tr -d " ;" ); do + _debug "check included $included" + if _checkConf "$1" "$included"; then + return 0 + fi + done + fi + return 1 + else + _debug "$2 not found." + return 1 + fi + return 1 +} + +#d , conf +_isRealNginxConf() { + _debug "_isRealNginxConf $1 $2" + if [ -f "$2" ] && grep "^ *server_name " "$2" | grep " $1" >/dev/null; then + return 0 + else + return 1 + fi +} + +#restore all the nginx conf +_restoreNginx() { + if [ -z "$NGINX_VLIST" ]; then + _debug "No need to restore nginx, skip." + return + fi + _debug "_restoreNginx" + _debug "NGINX_VLIST" "$NGINX_VLIST" + + for ng_entry in $(echo "$NGINX_VLIST" | tr "$dvsep" ' '); do + _debug "ng_entry" "$ng_entry" + _nd=$(echo "$ng_entry" | cut -d "$sep" -f 1) + _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) + _ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3) + _info "Restoring from $_ngbackupconf to $_ngconf" + cat "$_ngbackupconf" > "$_ngconf" + done + + _info "Reload nginx" + if ! _exec "nginx -s reload" >/dev/null; then + _exec_err + _err "It seems that nginx reload error, please report bug." + return 1 + fi + return 0 +} + _clearup() { _stopserver "$serverproc" serverproc="" _restoreApache + _restoreNginx _clearupdns if [ -z "$DEBUG" ]; then rm -f "$TLS_CONF" @@ -2822,6 +3000,7 @@ issue() { _info "Getting domain auth token for each domain" sep='#' + dvsep=',' if [ -z "$vlist" ]; then alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ') _index=1 @@ -2829,7 +3008,7 @@ issue() { for d in $alldomains; do _info "Getting webroot for domain" "$d" _w="$(echo $Le_Webroot | cut -d , -f $_index)" - _info _w "$_w" + _debug _w "$_w" if [ "$_w" ]; then _currentRoot="$_w" fi @@ -2881,13 +3060,13 @@ issue() { dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" _debug dvlist "$dvlist" - vlist="$vlist$dvlist," + vlist="$vlist$dvlist$dvsep" done - + _debug vlist "$vlist" #add entry dnsadded="" - ventries=$(echo "$vlist" | tr ',' ' ') + ventries=$(echo "$vlist" | tr "$dvsep" ' ') for ventry in $ventries; do d=$(echo "$ventry" | cut -d "$sep" -f 1) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) @@ -2970,10 +3149,11 @@ issue() { _sleep "$Le_DNSSleep" fi + NGINX_VLIST="" _debug "ok, let's start to verify" _ncIndex=1 - ventries=$(echo "$vlist" | tr ',' ' ') + ventries=$(echo "$vlist" | tr "$dvsep" ' ') for ventry in $ventries; do d=$(echo "$ventry" | cut -d "$sep" -f 1) keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) @@ -3012,6 +3192,22 @@ issue() { elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then _info "Stateless mode for domain:$d" _sleep 1 + elif _startswith "$_currentRoot" "$NGINX"; then + _info "Nginx mode for domain:$d" + #set up nginx server + FOUND_REAL_NGINX_CONF="" + BACKUP_NGINX_CONF="" + if ! _setNginx "$d" "$_currentRoot" "$thumbprint"; then + _clearup + _on_issue_err + return 1 + else + _realConf="$FOUND_REAL_NGINX_CONF" + _backup="$BACKUP_NGINX_CONF" + _debug _realConf "$_realConf" + NGINX_VLIST="$NGINX_VLIST$d$sep$_realConf$sep$_backup$dvsep" + fi + _sleep 1 else if [ "$_currentRoot" = "apache" ]; then wellknown_path="$ACME_DIR" @@ -4629,6 +4825,14 @@ _process() { _webroot="$_webroot,$wvalue" fi ;; + --nginx) + wvalue="$NGINX" + if [ -z "$_webroot" ]; then + _webroot="$wvalue" + else + _webroot="$_webroot,$wvalue" + fi + ;; --tls) wvalue="$W_TLS" if [ -z "$_webroot" ]; then From 03f8d6e946d642c529927668c078df2025f7aa22 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:03:48 +0800 Subject: [PATCH 02/13] fix https://github.com/Neilpang/acme.sh/issues/615 --- acme.sh | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/acme.sh b/acme.sh index 612c2094..349e1b39 100755 --- a/acme.sh +++ b/acme.sh @@ -46,6 +46,8 @@ MODE_STATELESS="stateless" STATE_VERIFIED="verified_ok" NGINX="nginx:" +NGINX_START="#ACME_NGINX_START" +NGINX_END="#ACME_NGINX_END" BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----" END_CSR="-----END CERTIFICATE REQUEST-----" @@ -2312,13 +2314,26 @@ _setNginx() { fi _start_f="$NGINX_CONF" fi - _info "Start detect nginx conf for $_d from:$_start_f" + _debug "Start detect nginx conf for $_d from:$_start_f" if ! _checkConf "$_d" "$_start_f"; then "Can not find conf file for domain $d" return 1 fi _info "Found conf file: $FOUND_REAL_NGINX_CONF" + _ln=$(grep -n "^ *server_name.* $_d" "$FOUND_REAL_NGINX_CONF" | cut -d : -f 1 | tr -d "\n") + _debug "_ln" "$_ln" + + _lnn=$(_math $_ln + 1) + _debug _lnn "$_lnn" + _start_tag="$(sed -n "$_lnn,${_lnn}p" "$FOUND_REAL_NGINX_CONF")" + _debug "_start_tag" "$_start_tag" + if [ "$_start_tag" = "$NGINX_START" ]; then + _info "The domain $_d is already configured, skip" + FOUND_REAL_NGINX_CONF="" + return 0 + fi + mkdir -p "$DOMAIN_BACKUP_PATH" _backup_conf="$DOMAIN_BACKUP_PATH/$_d.nginx.conf" _debug _backup_conf "$_backup_conf" @@ -2337,25 +2352,23 @@ _setNginx() { fi _info "OK, Set up nginx config file" - _ln=$(grep -n "^ *server_name.* $_d" "$_backup_conf" | cut -d : -f 1 | tr -d "\n") - _debug "_ln" "$_ln" if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored to the original version." return 1 fi - echo " + echo "$NGINX_START location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { default_type text/plain; return 200 \"\$1.$_thumbpt\"; } -" >> "$FOUND_REAL_NGINX_CONF" +#NGINX_START +" >>"$FOUND_REAL_NGINX_CONF" - _ln=$(_math $_ln + 1) - if ! sed -n "${_ln},99999p" "$_backup_conf" >> "$FOUND_REAL_NGINX_CONF"; then - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + if ! sed -n "${_lnn},99999p" "$_backup_conf" >>"$FOUND_REAL_NGINX_CONF"; then + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored." return 1 fi @@ -2364,7 +2377,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -t" >/dev/null; then _exec_err _err "It seems that nginx conf was broken, let's restore." - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2372,7 +2385,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -s reload" >/dev/null; then _exec_err _err "It seems that nginx reload error, let's restore." - cat "$_backup_conf" > "$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -3201,7 +3214,9 @@ issue() { _clearup _on_issue_err return 1 - else + fi + + if [ "$FOUND_REAL_NGINX_CONF" ]; then _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" _debug _realConf "$_realConf" From 5d943a35f8341660c0429e11ea5299bfb008689d Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:12:58 +0800 Subject: [PATCH 03/13] fix https://github.com/Neilpang/acme.sh/issues/616 --- acme.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 349e1b39..6234500e 100755 --- a/acme.sh +++ b/acme.sh @@ -2442,14 +2442,14 @@ _isRealNginxConf() { #restore all the nginx conf _restoreNginx() { - if [ -z "$NGINX_VLIST" ]; then + if [ -z "$NGINX_RESTORE_VLIST" ]; then _debug "No need to restore nginx, skip." return fi _debug "_restoreNginx" - _debug "NGINX_VLIST" "$NGINX_VLIST" + _debug "NGINX_RESTORE_VLIST" "$NGINX_RESTORE_VLIST" - for ng_entry in $(echo "$NGINX_VLIST" | tr "$dvsep" ' '); do + for ng_entry in $(echo "$NGINX_RESTORE_VLIST" | tr "$dvsep" ' '); do _debug "ng_entry" "$ng_entry" _nd=$(echo "$ng_entry" | cut -d "$sep" -f 1) _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) @@ -3162,7 +3162,7 @@ issue() { _sleep "$Le_DNSSleep" fi - NGINX_VLIST="" + NGINX_RESTORE_VLIST="" _debug "ok, let's start to verify" _ncIndex=1 @@ -3220,7 +3220,7 @@ issue() { _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" _debug _realConf "$_realConf" - NGINX_VLIST="$NGINX_VLIST$d$sep$_realConf$sep$_backup$dvsep" + NGINX_RESTORE_VLIST="$d$sep$_realConf$sep$_backup$dvsep$NGINX_RESTORE_VLIST" fi _sleep 1 else From 302c41edc9c8696f8f266352449eb7e8e2c79533 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 22:41:34 +0800 Subject: [PATCH 04/13] fix format --- acme.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index 6234500e..6121224f 100755 --- a/acme.sh +++ b/acme.sh @@ -2353,7 +2353,7 @@ _setNginx() { _info "OK, Set up nginx config file" - if ! sed -n "1,${_ln}p" "$_backup_conf" > "$FOUND_REAL_NGINX_CONF"; then + if ! sed -n "1,${_ln}p" "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"; then cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" _err "write nginx conf error, but don't worry, the file is restored to the original version." return 1 @@ -2377,7 +2377,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -t" >/dev/null; then _exec_err _err "It seems that nginx conf was broken, let's restore." - cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2385,7 +2385,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" { if ! _exec "nginx -s reload" >/dev/null; then _exec_err _err "It seems that nginx reload error, let's restore." - cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" + cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF" return 1 fi @@ -2415,7 +2415,7 @@ _checkConf() { fi if grep "^ *include *.*;" "$2" >/dev/null; then _debug "Try include files" - for included in $(grep "^ *include *.*;" "$2"| sed "s/include //" | tr -d " ;" ); do + for included in $(grep "^ *include *.*;" "$2" | sed "s/include //" | tr -d " ;"); do _debug "check included $included" if _checkConf "$1" "$included"; then return 0 @@ -2433,11 +2433,17 @@ _checkConf() { #d , conf _isRealNginxConf() { _debug "_isRealNginxConf $1 $2" - if [ -f "$2" ] && grep "^ *server_name " "$2" | grep " $1" >/dev/null; then + if [ -f "$2" ]; then + for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do + _debug _fln "$_fln" + if [ "$_fln" ]; then + _listen=$(cat "$2" | _head_n "$_fln" | grep "^ *listen .*" | _tail_n 1) + fi + done return 0 - else - return 1 fi + + return 1 } #restore all the nginx conf @@ -2455,7 +2461,7 @@ _restoreNginx() { _ngconf=$(echo "$ng_entry" | cut -d "$sep" -f 2) _ngbackupconf=$(echo "$ng_entry" | cut -d "$sep" -f 3) _info "Restoring from $_ngbackupconf to $_ngconf" - cat "$_ngbackupconf" > "$_ngconf" + cat "$_ngbackupconf" >"$_ngconf" done _info "Reload nginx" @@ -3215,7 +3221,7 @@ issue() { _on_issue_err return 1 fi - + if [ "$FOUND_REAL_NGINX_CONF" ]; then _realConf="$FOUND_REAL_NGINX_CONF" _backup="$BACKUP_NGINX_CONF" From 9f90618a707750475604f5ad8bf726f62f281c67 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 14 Feb 2017 23:57:00 +0800 Subject: [PATCH 05/13] fix https://github.com/Neilpang/acme.sh/issues/617 --- acme.sh | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 6121224f..a846b97a 100755 --- a/acme.sh +++ b/acme.sh @@ -2294,6 +2294,7 @@ _setNginx() { return 1 fi FOUND_REAL_NGINX_CONF="" + FOUND_REAL_NGINX_CONF_LN="" BACKUP_NGINX_CONF="" _debug _croot "$_croot" _start_f="$(echo "$_croot" | cut -d : -f 2)" @@ -2321,7 +2322,7 @@ _setNginx() { fi _info "Found conf file: $FOUND_REAL_NGINX_CONF" - _ln=$(grep -n "^ *server_name.* $_d" "$FOUND_REAL_NGINX_CONF" | cut -d : -f 1 | tr -d "\n") + _ln=$FOUND_REAL_NGINX_CONF_LN _debug "_ln" "$_ln" _lnn=$(_math $_ln + 1) @@ -2437,12 +2438,36 @@ _isRealNginxConf() { for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do _debug _fln "$_fln" if [ "$_fln" ]; then - _listen=$(cat "$2" | _head_n "$_fln" | grep "^ *listen .*" | _tail_n 1) + _start=$(cat "$2" | _head_n "$_fln" | grep -n "^ *server *{" | _tail_n 1) + _debug "_start" "$_start" + _start_n=$(echo "$_start" | cut -d : -f 1) + _start_nn=$(_math $_start_n + 1) + _debug "_start_n" "$_start_n" + _debug "_start_nn" "$_start_nn" + + _left="$(sed -n "${_start_nn},99999p" "$2")" + _debug2 _left "$_left" + if echo "$_left" | grep -n "^ *server *{" >/dev/null; then + _end=$(echo "$_left" | grep -n "^ *server *{" | _head_n 1) + _debug "_end" "$_end" + _end_n=$(echo "$_end" | cut -d : -f 1) + _debug "_end_n" "$_end_n" + _seg_n=$(echo "$_left" | sed -n "1,${_end_n}p") + else + _seg_n="$_left" + fi + + _debug "_seg_n" "$_seg_n" + + if [ "$(echo "$_seg_n" | _egrep_o "^ *ssl *on *;")" ]; then + _debug "ssl on, skip" + return 1 + fi + FOUND_REAL_NGINX_CONF_LN=$_fln + return 0 fi done - return 0 fi - return 1 } From 6921211461a1c4d7d24c21643ead5d56d15ea532 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 20:24:24 +0800 Subject: [PATCH 06/13] fix debug message --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index a846b97a..5e84eeaa 100755 --- a/acme.sh +++ b/acme.sh @@ -2528,7 +2528,7 @@ _clearupdns() { txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)" _debug txt "$txt" if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _info "$d is already verified, skip $vtype." + _debug "$d is already verified, skip $vtype." continue fi @@ -3096,7 +3096,7 @@ issue() { _debug keyauthorization "$keyauthorization" if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then - _info "$d is already verified, skip." + _debug "$d is already verified, skip." keyauthorization="$STATE_VERIFIED" _debug keyauthorization "$keyauthorization" fi @@ -3118,7 +3118,7 @@ issue() { _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then - _info "$d is already verified, skip $vtype." + _debug "$d is already verified, skip $vtype." continue fi From 7db28745c89b168d55b26ab68d696b069d091c23 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 20:28:50 +0800 Subject: [PATCH 07/13] start v2.6.7 --- README.md | 2 +- acme.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index edc4555c..2624690a 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ https://github.com/Neilpang/acmetest - Webroot mode - Standalone mode - Apache mode -- Nginx mode +- Nginx mode ( Beta ) - DNS mode - [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) diff --git a/acme.sh b/acme.sh index 5e84eeaa..7a229eb6 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.6.6 +VER=2.6.7 PROJECT_NAME="acme.sh" From 72af092cc1ac37908954366edf3abf05d7fae4be Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 15 Feb 2017 21:09:01 +0800 Subject: [PATCH 08/13] fix https://github.com/Neilpang/acme.sh/issues/614 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7a229eb6..36443e39 100755 --- a/acme.sh +++ b/acme.sh @@ -994,7 +994,7 @@ _readKeyLengthFromCSR() { 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 + echo "$_outcsr" | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 fi } From ad153ae041f40c4c4d730f35d9e58700ccd25906 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 16 Feb 2017 22:29:08 +0800 Subject: [PATCH 09/13] fix https://github.com/Neilpang/acme.sh/issues/622 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 36443e39..cf9d8501 100755 --- a/acme.sh +++ b/acme.sh @@ -1610,14 +1610,14 @@ _setopt() { __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then if _contains "$__val" "&"; then __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" else _debug3 APP From 52f8b787c981ffc761694ad979d58b86390ca9f5 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 16 Feb 2017 22:37:32 +0800 Subject: [PATCH 10/13] fix https://github.com/Neilpang/acme.sh/issues/622 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index cf9d8501..a590d10e 100755 --- a/acme.sh +++ b/acme.sh @@ -1610,14 +1610,14 @@ _setopt() { __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - printf -- "%s" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" elif grep -n "^#$__opt$__sep" "$__conf" >/dev/null; then if _contains "$__val" "&"; then __val="$(echo "$__val" | sed 's/&/\\&/g')" fi text="$(cat "$__conf")" - printf -- "%s" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" + printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf" else _debug3 APP From 0bc745f68fa9ca0dbb5350bf51ea65f3865824a9 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 17 Feb 2017 13:51:17 +0800 Subject: [PATCH 11/13] retry if nonce is invalid fix https://github.com/Neilpang/acme.sh/issues/627 --- acme.sh | 103 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/acme.sh b/acme.sh index a590d10e..d3d3d507 100755 --- a/acme.sh +++ b/acme.sh @@ -1530,62 +1530,75 @@ _send_signed_request() { payload64=$(printf "%s" "$payload" | _base64 | _url_replace) _debug3 payload64 "$payload64" - if [ -z "$_CACHED_NONCE" ]; then - _debug2 "Get nonce." - nonceurl="$API/directory" - _headers="$(_get "$nonceurl" "onlyheader")" + MAX_REQUEST_RETRY_TIMES=5 + _request_retry_times=0 + while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do + _debug3 _request_retry_times "$_request_retry_times" + if [ -z "$_CACHED_NONCE" ]; then + _debug2 "Get nonce." + nonceurl="$API/directory" + _headers="$(_get "$nonceurl" "onlyheader")" - if [ "$?" != "0" ]; then - _err "Can not connect to $nonceurl to get nonce." + if [ "$?" != "0" ]; then + _err "Can not connect to $nonceurl to get nonce." + return 1 + fi + + _debug2 _headers "$_headers" + + _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + _debug2 _CACHED_NONCE "$_CACHED_NONCE" + else + _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" + fi + nonce="$_CACHED_NONCE" + _debug2 nonce "$nonce" + + protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2" + _debug3 protected "$protected" + + protected64="$(printf "%s" "$protected" | _base64 | _url_replace)" + _debug3 protected64 "$protected64" + + if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then + _err "Sign request failed." return 1 fi + _debug3 _sig_t "$_sig_t" - _debug2 _headers "$_headers" + sig="$(printf "%s" "$_sig_t" | _url_replace)" + _debug3 sig "$sig" - _CACHED_NONCE="$(echo "$_headers" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" - _debug2 _CACHED_NONCE "$_CACHED_NONCE" - else - _debug2 "Use _CACHED_NONCE" "$_CACHED_NONCE" - fi - nonce="$_CACHED_NONCE" - _debug2 nonce "$nonce" + body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" + _debug3 body "$body" - protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2" - _debug3 protected "$protected" + response="$(_post "$body" "$url" "$needbase64")" + _CACHED_NONCE="" - protected64="$(printf "%s" "$protected" | _base64 | _url_replace)" - _debug3 protected64 "$protected64" + if [ "$?" != "0" ]; then + _err "Can not post to $url" + return 1 + fi + _debug2 original "$response" + response="$(echo "$response" | _normalizeJson)" - if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then - _err "Sign request failed." - return 1 - fi - _debug3 _sig_t "$_sig_t" + responseHeaders="$(< "$HTTP_HEADER")" - sig="$(printf "%s" "$_sig_t" | _url_replace)" - _debug3 sig "$sig" + _debug2 responseHeaders "$responseHeaders" + _debug2 response "$response" + code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" + _debug code "$code" - body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" - _debug3 body "$body" + _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" - response="$(_post "$body" "$url" "$needbase64")" - _CACHED_NONCE="" - if [ "$?" != "0" ]; then - _err "Can not post to $url" - return 1 - fi - _debug2 original "$response" - - response="$(echo "$response" | _normalizeJson)" - - responseHeaders="$(cat "$HTTP_HEADER")" - - _debug2 responseHeaders "$responseHeaders" - _debug2 response "$response" - code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" - _debug code "$code" - - _CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)" + if _contains "$response" "JWS has invalid anti-replay nonce"; then + _info "It seems the CA server is busy now, let's wait and retry." + _request_retry_times=$(_math "$_request_retry_times" + 1) + _sleep 5 + continue + fi + break; + done } From b7924ce58b09927c606615b7a485d6870073d0b0 Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 17 Feb 2017 14:40:58 +0800 Subject: [PATCH 12/13] fix format --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index d3d3d507..7eee2909 100755 --- a/acme.sh +++ b/acme.sh @@ -1533,7 +1533,7 @@ _send_signed_request() { MAX_REQUEST_RETRY_TIMES=5 _request_retry_times=0 while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do - _debug3 _request_retry_times "$_request_retry_times" + _debug3 _request_retry_times "$_request_retry_times" if [ -z "$_CACHED_NONCE" ]; then _debug2 "Get nonce." nonceurl="$API/directory" @@ -1582,7 +1582,7 @@ _send_signed_request() { _debug2 original "$response" response="$(echo "$response" | _normalizeJson)" - responseHeaders="$(< "$HTTP_HEADER")" + responseHeaders="$(<"$HTTP_HEADER")" _debug2 responseHeaders "$responseHeaders" _debug2 response "$response" @@ -1597,7 +1597,7 @@ _send_signed_request() { _sleep 5 continue fi - break; + break done } From c70432996a70c82bdb4af526496bbc9b33408ab3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 17 Feb 2017 23:06:39 +0800 Subject: [PATCH 13/13] compatible to openssl 0.9 for hmac function --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 7eee2909..d36df7f7 100755 --- a/acme.sh +++ b/acme.sh @@ -740,9 +740,9 @@ _hmac() { if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then if [ "$outputhex" ]; then - $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" | cut -d = -f 2 | tr -d ' ' + ($OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' ' else - $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary + $OPENSSL_BIN dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || $OPENSSL_BIN dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary fi else _err "$alg is not supported yet"