Example #1
0
// Handle responds to requests for a ocsp signature. It creates and signs
// a ocsp response for the provided certificate and status. If the status
// is revoked then it also adds reason and revoked_at. The response is
// base64 encoded.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	r.Body.Close()

	// Default the status to good so it matches the cli
	req := &jsonSignRequest{
		Status: "good",
	}
	err = json.Unmarshal(body, req)
	if err != nil {
		return errors.NewBadRequestString("Unable to parse sign request")
	}

	cert, err := helpers.ParseCertificatePEM([]byte(req.Certificate))
	if err != nil {
		log.Error("Error from ParseCertificatePEM", err)
		return errors.NewBadRequestString("Malformed certificate")
	}

	signReq := ocsp.SignRequest{
		Certificate: cert,
		Status:      req.Status,
	}
	// We need to convert the time from being a string to a time.Time
	if req.Status == "revoked" {
		signReq.Reason = req.Reason
		// "now" is accepted and the default on the cli so default that here
		if req.RevokedAt == "" || req.RevokedAt == "now" {
			signReq.RevokedAt = time.Now()
		} else {
			signReq.RevokedAt, err = time.Parse("2006-01-02", req.RevokedAt)
			if err != nil {
				return errors.NewBadRequestString("Malformed revocation time")
			}
		}
	}
	if req.IssuerHash != "" {
		issuerHash, ok := nameToHash[req.IssuerHash]
		if !ok {
			return errors.NewBadRequestString("Unsupported hash algorithm in request")
		}
		signReq.IssuerHash = issuerHash
	}

	resp, err := h.signer.Sign(signReq)
	if err != nil {
		return err
	}

	b64Resp := base64.StdEncoding.EncodeToString(resp)
	result := map[string]string{"ocspResponse": b64Resp}
	return api.SendResponse(w, result)
}
Example #2
0
// ocspSignerMain is the main CLI of OCSP signer functionality.
func ocspSignerMain(args []string, c cli.Config) (err error) {
	// Read the cert to be revoked from file
	certBytes, err := ioutil.ReadFile(c.CertFile)
	if err != nil {
		log.Critical("Unable to read certificate: ", err)
		return
	}
	cert, err := helpers.ParseCertificatePEM(certBytes)
	if err != nil {
		log.Critical("Unable to parse certificate: ", err)
		return
	}

	req := ocsp.SignRequest{
		Certificate: cert,
		Status:      c.Status,
	}

	if c.Status == "revoked" {
		var reasonCode int
		reasonCode, err = ocsp.ReasonStringToCode(c.Reason)
		if err != nil {
			log.Critical("Invalid reason code: ", err)
			return
		}

		req.Reason = reasonCode
		req.RevokedAt = time.Now()
		if c.RevokedAt != "now" {
			req.RevokedAt, err = time.Parse("2006-01-02", c.RevokedAt)
			if err != nil {
				log.Critical("Malformed revocation time: ", c.RevokedAt)
				return
			}
		}
	}

	s, err := SignerFromConfig(c)
	if err != nil {
		log.Critical("Unable to create OCSP signer: ", err)
		return
	}

	resp, err := s.Sign(req)
	if err != nil {
		log.Critical("Unable to sign OCSP response: ", err)
		return
	}

	cli.PrintOCSPResponse(resp)
	return
}
// ocsprefreshMain is the main CLI of OCSP refresh functionality.
func ocsprefreshMain(args []string, c cli.Config) error {
	if c.DBConfigFile == "" {
		return errors.New("need DB config file (provide with -db-config)")
	}

	if c.ResponderFile == "" {
		return errors.New("need responder certificate (provide with -responder)")
	}

	if c.ResponderKeyFile == "" {
		return errors.New("need responder key (provide with -responder-key)")
	}

	if c.CAFile == "" {
		return errors.New("need CA certificate (provide with -ca)")
	}

	s, err := SignerFromConfig(c)
	if err != nil {
		log.Critical("Unable to create OCSP signer: ", err)
		return err
	}

	db, err := dbconf.DBFromConfig(c.DBConfigFile)
	if err != nil {
		return err
	}

	dbAccessor := sql.NewAccessor(db)
	certs, err := dbAccessor.GetUnexpiredCertificates()
	if err != nil {
		return err
	}

	// Set an expiry timestamp for all certificates refreshed in this batch
	ocspExpiry := time.Now().Add(c.Interval)
	for _, certRecord := range certs {
		cert, err := helpers.ParseCertificatePEM([]byte(certRecord.PEM))
		if err != nil {
			log.Critical("Unable to parse certificate: ", err)
			return err
		}

		req := ocsp.SignRequest{
			Certificate: cert,
			Status:      certRecord.Status,
		}

		if certRecord.Status == "revoked" {
			req.Reason = int(certRecord.Reason)
			req.RevokedAt = certRecord.RevokedAt
		}

		resp, err := s.Sign(req)
		if err != nil {
			log.Critical("Unable to sign OCSP response: ", err)
			return err
		}

		err = dbAccessor.UpsertOCSP(cert.SerialNumber.String(), hex.EncodeToString(cert.AuthorityKeyId), string(resp), ocspExpiry)
		if err != nil {
			log.Critical("Unable to save OCSP response: ", err)
			return err
		}
	}

	return nil
}