Skip to content

Commit 4487d92

Browse files
committed
Handle multiple contact e-mail addresses
Handle e-mail update with buggy 409 responses from registration. Improve contact parsing by replacing call to json_get, which doesn't seem to handle string array values well. (It's also easier to parse the values at the same time.) No reason to save register response JSON in TEMP_DIR, so don't. Appears to be stale debugging code. Exit after deactivating account.
1 parent 186a285 commit 4487d92

1 file changed

Lines changed: 82 additions & 35 deletions

File tree

getssl

Lines changed: 82 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@
298298
# 2024-03-21 Relax restrictions on dns-01 CNAMEs to allow for hased targets. (tlhackque)
299299
# 2024-03-21 Ensure that --all doesn't run --new-account-key or --DEACTIVATE-account more than once. (tlhackque)
300300
# 2024-03-21 Avoid domain processing when the action is account management. (tlhackque)
301+
# 2024-03-24 Implement multiple ACCOUNT_EMAIL addresses (tlhackque)
301302
# ----------------------------------------------------------------------------------------
302303

303304
case :$SHELLOPTS: in
@@ -435,6 +436,23 @@ base64url_decode() {
435436
awk '{ if (length($0) % 4 == 3) print $0"="; else if (length($0) % 4 == 2) print $0"=="; else print $0; }' | tr -- '-_' '+/' | base64 -d
436437
}
437438

439+
# Convert arguments to comma-separated list
440+
function Join() {
441+
local IFS=","
442+
printf '%s' "$*"
443+
}
444+
445+
# Sort array "sortin" to "sortout" (with -u)
446+
function sorta() {
447+
local i _line
448+
sorted=()
449+
while IFS=$'\n' read -r _line ; do
450+
sorted+=( "$_line" )
451+
done < <( for (( i=0; i < "${#sortin[@]}"; ++i )); do
452+
printf '%s\n' "${sortin["$i"]}"
453+
done | sort -u )
454+
}
455+
438456
cert_install() { # copy certs to the correct location (creating concatenated files as required)
439457
umask 077
440458

@@ -2845,8 +2863,10 @@ write_getssl_template() { # write out the main template file
28452863
# The agreement that must be signed with the CA, if not defined the default agreement will be used
28462864
#AGREEMENT="$AGREEMENT"
28472865
2848-
# Set an email address associated with your account - generally set at account level rather than domain.
2866+
# Set one or more email addresses associated with your account - generally set at account level rather than domain.
28492867
#ACCOUNT_EMAIL="me@example.com"
2868+
#ACCOUNT_EMAIL=("me@example.com" "you@example.com")
2869+
28502870
ACCOUNT_KEY_LENGTH=4096
28512871
ACCOUNT_KEY="$WORKING_DIR/account.key"
28522872
@@ -3496,58 +3516,84 @@ fi
34963516
get_signing_params "$ACCOUNT_KEY"
34973517

34983518
info "Registering account"
3519+
3520+
# Convert contact e-mail addresses to mailto: format. Sort for comparisons.
3521+
if [[ -n "${ACCOUNT_EMAIL[*]}" ]] ; then
3522+
IFS=',' read -ra "ACCOUNT_EMAIL" <<<"$(Join "${ACCOUNT_EMAIL[@]}")"
3523+
sortin=()
3524+
for em in "${ACCOUNT_EMAIL[@]}"; do
3525+
sortin+=("\"mailto:$em\"")
3526+
done
3527+
sorta
3528+
ACCOUNT_EMAIL=("${sorted[@]}")
3529+
account_emails="$(Join "${ACCOUNT_EMAIL[@]}")"
3530+
else
3531+
account_emails=
3532+
fi
3533+
34993534
# send the request to the ACME server.
35003535
if [[ $API -eq 1 ]]; then
3501-
if [[ "$ACCOUNT_EMAIL" ]] ; then
3502-
regjson='{"resource": "new-reg", "contact": ["mailto:'$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}'
3536+
if [[ -n "$account_emails" ]]; then
3537+
regjson='{"resource": "new-reg", "agreement": "'"$AGREEMENT"'", "contact": [ '"${account_emails}"' ]}'
35033538
else
3504-
regjson='{"resource": "new-reg", "agreement": "'$AGREEMENT'"}'
3539+
regjson='{"resource": "new-reg", "agreement": "'"$AGREEMENT"'"}'
35053540
fi
35063541
send_signed_request "$URL_new_reg" "$regjson"
35073542
elif [[ $API -eq 2 ]]; then
3508-
if [[ "$ACCOUNT_EMAIL" ]] ; then
3509-
regjson='{"termsOfServiceAgreed": true, "contact": ["mailto:'$ACCOUNT_EMAIL'"]}'
3543+
if [[ -n "$account_emails" ]] ; then
3544+
regjson='{"termsOfServiceAgreed": true, "contact": [ '"${account_emails}"' ]}'
35103545
else
35113546
regjson='{"termsOfServiceAgreed": true}'
35123547
fi
35133548
send_signed_request "$URL_newAccount" "$regjson"
35143549
else
3515-
debug "cant determine account API"
3516-
graceful_exit
3550+
debug "cant determine account API"
3551+
graceful_exit
35173552
fi
35183553

35193554
if [[ "$code" == "" ]] || [[ "$code" == '201' ]] ; then
35203555
info "Registered"
35213556
KID=$(echo "$responseHeaders" | grep -i "^location" | awk '{print $2}'| tr -d '\r\n ')
35223557
debug "AccountId=$KID}"
3523-
echo "$response" > "$TEMP_DIR/account.json"
3524-
elif [[ "$code" == '409' ]] ; then
3525-
KID=$(echo "$responseHeaders" | grep -i "^location" | awk '{print $2}'| tr -d '\r\n ')
3526-
debug responseHeaders "$responseHeaders"
3527-
debug "Already registered, AccountId=$KID"
3528-
elif [[ "$code" == '200' ]] ; then
3529-
KID=$(echo "$responseHeaders" | grep -i "^location" | awk '{print $2}'| tr -d '\r\n ')
3530-
debug responseHeaders "$responseHeaders"
3531-
debug "Already registered account, AccountId=${KID}"
3532-
email="$(json_get "$response" "contact")"
3533-
if [[ "${email#mailto:}" != "$ACCOUNT_EMAIL" ]]; then
3534-
# Update account E-Mail (Note that a list is allowed by the RFC)
3535-
if [[ -n "$ACCOUNT_EMAIL" ]]; then
3536-
info "Updating account contact e-mail from '${email#mailto:}' to '$ACCOUNT_EMAIL'"
3537-
send_signed_request "$KID" '{"contact": ["mailto:'"$ACCOUNT_EMAIL"'"]}'
3538-
else
3539-
info "Removing account contact email '${email#mailto:}'"
3540-
send_signed_request "$KID" '{"contact": []}'
3541-
fi
3542-
if [[ "$code" == '200' ]]; then
3543-
info " - update succeeded"
3544-
else
3545-
info " - update failed"
3546-
fi
3547-
debug responseHeaders "$responseHeaders"
3548-
fi
35493558
else
3550-
error_exit "Error registering account ...$responseHeaders ... $(json_get "$response" detail)"
3559+
if [[ "$code" == '409' ]] ; then
3560+
KID=$(echo "$responseHeaders" | grep -i "^location" | awk '{print $2}'| tr -d '\r\n ')
3561+
debug responseHeaders "$responseHeaders"
3562+
debug "Already registered with 'conflict' response (boulder issue 3327), AccountId=$KID"
3563+
elif [[ "$code" == '200' ]] ; then
3564+
KID=$(echo "$responseHeaders" | grep -i "^location" | awk '{print $2}'| tr -d '\r\n ')
3565+
debug responseHeaders "$responseHeaders"
3566+
debug "Already registered account, AccountId=${KID}"
3567+
else
3568+
error_exit "Error registering account ...$responseHeaders ... $(json_get "$response" detail)"
3569+
fi
3570+
3571+
#email="$(json_get "$response" "contact")"
3572+
#if schemes other than mailto: are supported, this will need to change
3573+
r="$(tr '\n\t' ' ' <<<"$response")"
3574+
reg_mailto=
3575+
if [[ "$r" =~ '"contact"'\ *:\ *'['\ *(('"mailto:'[^\"]*\",?\ *)+\ *)']' ]]; then
3576+
sortin=()
3577+
IFS=',' read -ra "sortin" < <(sed -e's/, */,/g;s/ *$//' <<<"${BASH_REMATCH[1]}")
3578+
sorta; reg_mailto="$(Join "${sorted[@]}")"
3579+
fi
3580+
unset r
3581+
if [[ "${reg_mailto}" != "${account_emails}" ]]; then
3582+
# Update account E-Mail
3583+
if [[ -n "${account_emails}" ]]; then
3584+
info "Updating account contact e-mail from '${reg_mailto}' to '${account_emails}'"
3585+
send_signed_request "$KID" '{"contact": [ '"${account_emails}"' ]}'
3586+
else
3587+
info "Removing account contact email '${account_emails}'"
3588+
send_signed_request "$KID" '{"contact": []}'
3589+
fi
3590+
if [[ "$code" == '200' ]]; then
3591+
info " - update succeeded"
3592+
else
3593+
info " - update failed"
3594+
fi
3595+
debug responseHeaders "$responseHeaders"
3596+
fi
35513597
fi
35523598
35533599
if [[ ${_SHOW_ACCOUNT_ID} -eq 1 ]]; then
@@ -3601,6 +3647,7 @@ if [[ ${_DEACTIVATE_ACCOUNT} -eq 1 ]]; then
36013647
info " - deactivation failed"
36023648
fi
36033649
debug responseHeaders "$responseHeaders"
3650+
graceful_exit
36043651
fi
36053652
# end of deactivate account
36063653

0 commit comments

Comments
 (0)