acme/autocert: surface details of acme.AuthorizationError

Fixes golang/go#19800

Change-Id: If915a70f4dee78e71dcfc487726cdf83d45b4d50
Reviewed-on: https://go-review.googlesource.com/115938
Reviewed-by: Alex Vaghin <ddos@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/acme/autocert/autocert.go b/acme/autocert/autocert.go
index cd61353..c8fa4e6 100644
--- a/acme/autocert/autocert.go
+++ b/acme/autocert/autocert.go
@@ -658,6 +658,8 @@
 		}
 	}()
 
+	// errs accumulates challenge failure errors, printed if all fail
+	errs := make(map[*acme.Challenge]error)
 	var nextTyp int // challengeType index of the next challenge type to try
 	for {
 		// Start domain authorization and get the challenge.
@@ -683,22 +685,30 @@
 			nextTyp++
 		}
 		if chal == nil {
-			return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes)
+			errorMsg := fmt.Sprintf("acme/autocert: unable to authorize %q", domain)
+			for chal, err := range errs {
+				errorMsg += fmt.Sprintf("; challenge %q failed with error: %v", chal.Type, err)
+			}
+			return errors.New(errorMsg)
 		}
 		cleanup, err := m.fulfill(ctx, client, chal)
 		if err != nil {
+			errs[chal] = err
 			continue
 		}
 		defer cleanup()
 		if _, err := client.Accept(ctx, chal); err != nil {
+			errs[chal] = err
 			continue
 		}
 
 		// A challenge is fulfilled and accepted: wait for the CA to validate.
-		if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil {
-			delete(pendingAuthzs, authz.URI)
-			return nil
+		if _, err := client.WaitAuthorization(ctx, authz.URI); err != nil {
+			errs[chal] = err
+			continue
 		}
+		delete(pendingAuthzs, authz.URI)
+		return nil
 	}
 }