From 68ce90afe1c3554e230f11093ae726c397245f3c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 28 May 2019 04:08:09 -0600 Subject: [PATCH] better error handling --- app/js/bluecrypt-acme.js | 73 +++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/app/js/bluecrypt-acme.js b/app/js/bluecrypt-acme.js index 7453c14..1ca5704 100644 --- a/app/js/bluecrypt-acme.js +++ b/app/js/bluecrypt-acme.js @@ -1785,7 +1785,7 @@ ACME.challengeTests = { ACME._directory = function (me) { // GET-as-GET ok - return me.request({ method: 'GET', url: me.directoryUrl, json: true }); + return ACME._request(me, { method: 'GET', url: me.directoryUrl }); }; ACME._getNonce = function (me) { // GET-as-GET, HEAD-as-HEAD ok @@ -1800,7 +1800,8 @@ ACME._getNonce = function (me) { } } if (nonce) { return Promise.resolve(nonce.nonce); } - return me.request({ method: 'HEAD', url: me._directoryUrls.newNonce }).then(function (resp) { + // GET-as-GET ok + return ACME._request(me, { method: 'HEAD', url: me._directoryUrls.newNonce }).then(function (resp) { return resp.headers['replay-nonce']; }); }; @@ -2168,7 +2169,13 @@ ACME._postChallenge = function (me, options, auth) { count += 1; //#console.debug('\n[DEBUG] statusChallenge\n'); - return me.request({ method: 'GET', url: auth.url, json: true }).then(function (resp) { + // POST-as-GET + return ACME._jwsRequest(me, { + options: options + , url: auth.url + , protected: { kid: options._kid } + , payload: Enc.binToBuf(JSON.stringify({})) + }).then(function (resp) { if ('processing' === resp.body.status) { //#console.debug('poll: again'); return ACME._wait(RETRY_INTERVAL).then(pollStatus); @@ -2192,26 +2199,28 @@ ACME._postChallenge = function (me, options, auth) { return resp.body; } - var err; - if (resp.body.error && resp.body.error.detail) { - err = new Error("[acme-v2] " + auth.altname + " state:" + resp.body.status + " " + resp.body.error.detail); + var code = 'E_ACME_UNKNOWN'; + var err = new Error("[acme-v2] " + auth.altname + " (" + code + "): " + JSON.stringify(resp.body, null, 2)); + err.code = code; + + return Promise.reject(err); + }).catch(function (e) { + var err = e; + if (err.urn) { + err = new Error("[acme-v2] " + auth.altname + " status:" + e.status + " " + e.detail); err.auth = auth; err.altname = auth.altname; err.type = auth.type; - err.urn = resp.body.error.type; - err.code = ('invalid' === resp.body.status) ? 'E_CHALLENGE_INVALID' : 'E_CHALLENGE_UNKNOWN'; - err.uri = resp.body.url; - } else { - err = new Error("[acme-v2] " + auth.altname + " (E_STATE_UKN): " + JSON.stringify(resp.body, null, 2)); - err.code = 'E_CHALLENGE_UNKNOWN'; + err.code = ('invalid' === e.status) ? 'E_ACME_CHALLENGE' : 'E_ACME_UNKNOWN'; } - return Promise.reject(err); + throw err; }); } function respondToChallenge() { //#console.debug('[acme-v2.js] responding to accept challenge:'); + // POST-as-GET return ACME._jwsRequest(me, { options: options , url: auth.url @@ -2417,7 +2426,13 @@ ACME._finalizeOrder = function (me, options) { return pollCert(); }).then(function () { //#console.debug('acme-v2: order was finalized'); - return me.request({ method: 'GET', url: options._certificate, json: true }).then(function (resp) { + // POST-as-GET + return ACME._jwsRequest(me, { + options: options + , url: options._certificate + , protected: { kid: options._kid } + , payload: Enc.binToBuf(JSON.stringify({})) + }).then(function (resp) { //#console.debug('acme-v2: csr submitted and cert received:'); // https://github.com/certbot/certbot/issues/5721 var certsarr = ACME.splitPemChain(ACME.formatPemChain((resp.body||''))); @@ -2618,6 +2633,7 @@ ACME.create = function create(me) { } var p = Promise.resolve(); if (!me.skipChallengeTest) { + // Not ACME p = me.request({ url: me._baseUrl + "/api/_acme_api_/" }).then(function (resp) { if (resp.body.success) { me._canCheck['http-01'] = true; @@ -2687,10 +2703,35 @@ ACME._request = function (me, opts) { if (!opts.method) { opts.method = 'POST'; } } return me.request(opts).then(function (resp) { - resp = resp.toJSON(); + if (resp.toJSON) { resp = resp.toJSON(); } if (resp.headers['replay-nonce']) { ACME._setNonce(me, resp.headers['replay-nonce']); } + + var e; + var err; + if (resp.body) { + err = resp.body.error; + e = new Error(""); + if (400 === resp.body.status) { + err = { type: resp.body.type, detail: resp.body.detail }; + } + if (err) { + e.status = resp.body.status; + e.code = 'E_ACME'; + if (e.status) { + e.message = "[" + e.status + "] "; + } + e.detail = err.detail; + e.message += (err.detail || JSON.stringify(err)); + e.urn = err.type; + e.uri = resp.body.url; + e._rawError = err; + e._rawBody = resp.body; + throw e; + } + } + return resp; }); }; @@ -2771,6 +2812,7 @@ ACME._toHex = function (pair) { return parseInt(pair, 10).toString(16); }; ACME._dns01 = function (me, auth) { + // Not ACME return new me.request({ url: me._baseUrl + "/api/dns/" + auth.dnsHost + "?type=TXT" }).then(function (resp) { var err; if (!resp.body || !Array.isArray(resp.body.answer)) { @@ -2792,6 +2834,7 @@ ACME._dns01 = function (me, auth) { }; ACME._http01 = function (me, auth) { var url = encodeURIComponent(auth.challengeUrl); + // Not ACME return new me.request({ url: me._baseUrl + "/api/http?url=" + url }).then(function (resp) { return resp.body; });