Skip to content

Commit

Permalink
acme: implement POST-as-GET for accounts
Browse files Browse the repository at this point in the history
Some ACME clients POST-as-GET the account resource, expecting to
receive the account object (for an existing account).  In
particular, mod_md does this and certificate renewal fails when it
cannot read or verify the account information.

The ACME protocol does not explicitly require this behaviour.  But
on the other hand, it is not surprising that clients assume they can
do it, and it arguably is surprising if an ACME server does not
provide it.

So let's implement it.  The change itself is trivial: when payload
is empty, POST-as-GET is implied (RFC 8555 section 6.3).  In this
case, return the ACMEAccount object (which we already have at hand)
unchanged.
  • Loading branch information
frasertweedale authored and fmarco76 committed Nov 30, 2023
1 parent daffa76 commit eb5db84
Showing 1 changed file with 27 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,33 +74,40 @@ public Response updateAccount(@PathParam("id") String accountID, JWS jws) throws
engine.validateJWS(jws, header.getAlg(), account.getJWK());

String payload = new String(jws.getPayloadAsBytes(), "UTF-8");
logger.info("Payload: " + payload);

ACMEAccount update;
try {
update = ACMEAccount.fromJSON(payload);
} catch (JsonProcessingException e) {
throw engine.createMalformedException(e.toString());
if (payload.isEmpty()) {
logger.info("Empty payload; treating as POST-as-GET");
}

String newStatus = update.getStatus();
if (newStatus != null) {
logger.info("New status: " + newStatus);
account.setStatus(newStatus);
}
else {
logger.info("Payload: " + payload);

String[] newContact = update.getContact();
if (newContact != null) {
logger.info("New contact:");
for (String c : newContact) {
logger.info("- " + c);
ACMEAccount update;
try {
update = ACMEAccount.fromJSON(payload);
} catch (JsonProcessingException e) {
throw engine.createMalformedException(e.toString());
}

String newStatus = update.getStatus();
if (newStatus != null) {
logger.info("New status: " + newStatus);
account.setStatus(newStatus);
}

String[] newContact = update.getContact();
if (newContact != null) {
logger.info("New contact:");
for (String c : newContact) {
logger.info("- " + c);
}
account.setContact(newContact);
}
account.setContact(newContact);
}

engine.updateAccount(account);
engine.updateAccount(account);

// TODO: if account is deactivated, cancel all account's pending operations
// TODO: if account is deactivated, cancel all account's pending operations
}

// RFC 8555 Section 7.1.2.1 Orders List
//
Expand Down

0 comments on commit eb5db84

Please sign in to comment.