View definition


Defined in


NewCertificate is used by clients to request the issuance of a cert for an authorized identifier.

NewCertificate is referenced in 1 repository


		Registration core.Registration
		ClientAddr:   getClientAddr(request),
		CSR:          hex.EncodeToString(cr.Bytes),
		Registration: registration,
	wfe.log.AuditObject("Certificate request", csrLog)

// NewCertificate is used by clients to request the issuance of a cert for an
// authorized identifier.
func (wfe *WebFrontEndImpl) NewCertificate(ctx context.Context, logEvent *requestEvent, response http.ResponseWriter, request *http.Request) {
	body, _, reg, prob := wfe.verifyPOST(ctx, logEvent, request, true, core.ResourceNewCert)
	addRequesterHeader(response, logEvent.Requester)
	if prob != nil {
		// verifyPOST handles its own setting of logEvent.Errors
		wfe.sendError(response, logEvent, prob, nil)
	// Any version of the agreement is acceptable here. Version match is enforced in
	// wfe.Registration when agreeing the first time. Agreement updates happen
	// by mailing subscribers and don't require a registration update.
	if reg.Agreement == "" {
		wfe.sendError(response, logEvent, probs.Unauthorized("Must agree to subscriber agreement before any further actions"), nil)

	var rawCSR core.RawCertificateRequest
	err := json.Unmarshal(body, &rawCSR)
	if err != nil {
		logEvent.AddError("unable to JSON unmarshal CertificateRequest: %s", err)
		wfe.sendError(response, logEvent, probs.Malformed("Error unmarshaling certificate request"), err)
	// Assuming a properly formatted CSR there should be two four byte SEQUENCE
	// declarations then a two byte integer declaration which defines the version
	// of the CSR. If those two bytes (at offset 8 and 9) and equal to 2 and 0
	// then the CSR was generated by a pre-1.0.2 version of OpenSSL with a client
	// which didn't explicitly set the version causing the integer to be malformed
	// and encoding/asn1 will refuse to parse it. If this is the case exit early
	// with a more useful error message.
	if len(rawCSR.CSR) >= 10 && rawCSR.CSR[8] == 2 && rawCSR.CSR[9] == 0 {
		logEvent.AddError("Pre-1.0.2 OpenSSL malformed CSR")
		if wfe.CheckMalformedCSR {
				probs.Malformed("CSR generated using a pre-1.0.2 OpenSSL with a client that doesn't properly specify the CSR version"),

	certificateRequest := core.CertificateRequest{Bytes: rawCSR.CSR}
	certificateRequest.CSR, err = x509.ParseCertificateRequest(rawCSR.CSR)
	if err != nil {
		logEvent.AddError("unable to parse certificate request: %s", err)
		// TODO(jsha): Revert once #565 is closed by upgrading to Go 1.6, i.e. #1514
		wfe.sendError(response, logEvent, probs.Malformed("Error parsing certificate request. Extensions in the CSR marked critical can cause this error:"), err)
	wfe.logCsr(request, certificateRequest, reg)
	// Check that the key in the CSR is good. This will also be checked in the CA
	// component, but we want to discard CSRs with bad keys as early as possible
	// because (a) it's an easy check and we can save unnecessary requests and
	// bytes on the wire, and (b) the CA logs all rejections as audit events, but
	// a bad key from the client is just a malformed request and doesn't need to
	// be audited.
	if err := wfe.keyPolicy.GoodKey(certificateRequest.CSR.PublicKey); err != nil {
		logEvent.AddError("CSR public key failed GoodKey: %s", err)
		wfe.sendError(response, logEvent, probs.Malformed("Invalid key in certificate request :: %s", err), err)
	logEvent.Extra["CSRDNSNames"] = certificateRequest.CSR.DNSNames
	logEvent.Extra["CSREmailAddresses"] = certificateRequest.CSR.EmailAddresses
	logEvent.Extra["CSRIPAddresses"] = certificateRequest.CSR.IPAddresses

	// Create new certificate and return
	// TODO IMPORTANT: The RA trusts the WFE to provide the correct key. If the
	// WFE is compromised, *and* the attacker knows the public key of an account
	// authorized for target site, they could cause issuance for that site by
	// lying to the RA. We should probably pass a copy of the whole request to the
	// RA for secondary validation.
	cert, err := wfe.RA.NewCertificate(ctx, certificateRequest, reg.ID)
	if err != nil {
		logEvent.AddError("unable to create new cert: %s", err)
		wfe.sendError(response, logEvent, core.ProblemDetailsForError(err, "Error creating new cert"), err)

	// Make a URL for this certificate.
	// We use only the sequential part of the serial number, because it should
	// uniquely identify the certificate, and this makes it easy for anybody to
	// enumerate and mirror our certificates.
	parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
	if err != nil {
		logEvent.AddError("unable to parse certificate: %s", err)
		wfe.sendError(response, logEvent, probs.Malformed("Unable to parse certificate"), err)
	serial := parsedCertificate.SerialNumber
	certURL := wfe.relativeEndpoint(request, certPath+core.SerialToString(serial))

	relativeIssuerPath := wfe.relativeEndpoint(request, issuerPath)