Bug fix: Polling status using POST-as-GET wherever possible
Avoid repeating finalize POST request and challenge POST requests by using POST-as-GET requests instead. Allows for testing with Pebble, and more correctly follows the spec.
This commit is contained in:
		
							parent
							
								
									bef931f28f
								
							
						
					
					
						commit
						0aa939a227
					
				
							
								
								
									
										144
									
								
								acme.js
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								acme.js
									
									
									
									
									
								
							| @ -756,12 +756,8 @@ ACME._postChallenge = function (me, options, kid, auth) { | |||||||
| 			altname: altname | 			altname: altname | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		if ('processing' === resp.body.status) { | 		// State can be pending while waiting ACME server to transition to
 | ||||||
| 			//#console.debug('poll: again', auth.url);
 | 		// processing
 | ||||||
| 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// This state should never occur
 |  | ||||||
| 		if ('pending' === resp.body.status) { | 		if ('pending' === resp.body.status) { | ||||||
| 			if (count >= MAX_PEND) { | 			if (count >= MAX_PEND) { | ||||||
| 				return ACME._wait(RETRY_INTERVAL) | 				return ACME._wait(RETRY_INTERVAL) | ||||||
| @ -769,7 +765,12 @@ ACME._postChallenge = function (me, options, kid, auth) { | |||||||
| 					.then(respondToChallenge); | 					.then(respondToChallenge); | ||||||
| 			} | 			} | ||||||
| 			//#console.debug('poll: again', auth.url);
 | 			//#console.debug('poll: again', auth.url);
 | ||||||
| 			return ACME._wait(RETRY_INTERVAL).then(respondToChallenge); | 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ('processing' === resp.body.status) { | ||||||
|  | 			//#console.debug('poll: again', auth.url);
 | ||||||
|  | 			return ACME._wait(RETRY_INTERVAL).then(pollStatus); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// REMOVE DNS records as soon as the state is non-processing
 | 		// REMOVE DNS records as soon as the state is non-processing
 | ||||||
| @ -1012,73 +1013,84 @@ ACME._pollOrderStatus = function (me, options, kid, order, verifieds) { | |||||||
| 	var body = { csr: csr64 }; | 	var body = { csr: csr64 }; | ||||||
| 	var payload = JSON.stringify(body); | 	var payload = JSON.stringify(body); | ||||||
| 
 | 
 | ||||||
| 	function pollCert() { | 	function processResponse(resp) { | ||||||
|  | 		ACME._notify(me, options, 'certificate_status', { | ||||||
|  | 			subject: options.domains[0], | ||||||
|  | 			status: resp.body.status | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
 | ||||||
|  | 		// Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
 | ||||||
|  | 		if ('valid' === resp.body.status) { | ||||||
|  | 			var voucher = resp.body; | ||||||
|  | 			voucher._certificateUrl = resp.body.certificate; | ||||||
|  | 
 | ||||||
|  | 			return voucher; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ('processing' === resp.body.status) { | ||||||
|  | 			return ACME._wait().then(pollStatus); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (me.debug) { | ||||||
|  | 			console.debug( | ||||||
|  | 				'Error: bad status:\n' + JSON.stringify(resp.body, null, 2) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ('pending' === resp.body.status) { | ||||||
|  | 			return Promise.reject( | ||||||
|  | 				new Error( | ||||||
|  | 					"Did not finalize order: status 'pending'." + | ||||||
|  | 						' Best guess: You have not accepted at least one challenge for each domain:\n' + | ||||||
|  | 						"Requested: '" + | ||||||
|  | 						options.domains.join(', ') + | ||||||
|  | 						"'\n" + | ||||||
|  | 						"Validated: '" + | ||||||
|  | 						verifieds.join(', ') + | ||||||
|  | 						"'\n" + | ||||||
|  | 						JSON.stringify(resp.body, null, 2) | ||||||
|  | 				) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ('invalid' === resp.body.status) { | ||||||
|  | 			return Promise.reject( | ||||||
|  | 				E.ORDER_INVALID(options, verifieds, resp) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ('ready' === resp.body.status) { | ||||||
|  | 			return Promise.reject( | ||||||
|  | 				E.DOUBLE_READY_ORDER(options, verifieds, resp) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return Promise.reject( | ||||||
|  | 			E.UNHANDLED_ORDER_STATUS(options, verifieds, resp) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function pollStatus() { | ||||||
|  | 		return U._jwsRequest(me, { | ||||||
|  | 			accountKey: options.accountKey, | ||||||
|  | 			url: order._orderUrl, | ||||||
|  | 			protected: { kid: kid }, | ||||||
|  | 			payload: Enc.binToBuf('') | ||||||
|  | 		}).then(processResponse); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function finalizeOrder() { | ||||||
| 		//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
 | 		//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
 | ||||||
| 		return U._jwsRequest(me, { | 		return U._jwsRequest(me, { | ||||||
| 			accountKey: options.accountKey, | 			accountKey: options.accountKey, | ||||||
| 			url: order._finalizeUrl, | 			url: order._finalizeUrl, | ||||||
| 			protected: { kid: kid }, | 			protected: { kid: kid }, | ||||||
| 			payload: Enc.strToBuf(payload) | 			payload: Enc.strToBuf(payload) | ||||||
| 		}).then(function (resp) { | 		}).then(processResponse); | ||||||
| 			ACME._notify(me, options, 'certificate_status', { |  | ||||||
| 				subject: options.domains[0], |  | ||||||
| 				status: resp.body.status |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
 |  | ||||||
| 			// Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
 |  | ||||||
| 			if ('valid' === resp.body.status) { |  | ||||||
| 				var voucher = resp.body; |  | ||||||
| 				voucher._certificateUrl = resp.body.certificate; |  | ||||||
| 
 |  | ||||||
| 				return voucher; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if ('processing' === resp.body.status) { |  | ||||||
| 				return ACME._wait().then(pollCert); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (me.debug) { |  | ||||||
| 				console.debug( |  | ||||||
| 					'Error: bad status:\n' + JSON.stringify(resp.body, null, 2) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if ('pending' === resp.body.status) { |  | ||||||
| 				return Promise.reject( |  | ||||||
| 					new Error( |  | ||||||
| 						"Did not finalize order: status 'pending'." + |  | ||||||
| 							' Best guess: You have not accepted at least one challenge for each domain:\n' + |  | ||||||
| 							"Requested: '" + |  | ||||||
| 							options.domains.join(', ') + |  | ||||||
| 							"'\n" + |  | ||||||
| 							"Validated: '" + |  | ||||||
| 							verifieds.join(', ') + |  | ||||||
| 							"'\n" + |  | ||||||
| 							JSON.stringify(resp.body, null, 2) |  | ||||||
| 					) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if ('invalid' === resp.body.status) { |  | ||||||
| 				return Promise.reject( |  | ||||||
| 					E.ORDER_INVALID(options, verifieds, resp) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if ('ready' === resp.body.status) { |  | ||||||
| 				return Promise.reject( |  | ||||||
| 					E.DOUBLE_READY_ORDER(options, verifieds, resp) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			return Promise.reject( |  | ||||||
| 				E.UNHANDLED_ORDER_STATUS(options, verifieds, resp) |  | ||||||
| 			); |  | ||||||
| 		}); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return pollCert(); | 	return finalizeOrder(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ACME._redeemCert = function (me, options, kid, voucher) { | ACME._redeemCert = function (me, options, kid, voucher) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user