예제 #1
0
파일: revoke.go 프로젝트: nathany/cfssl
// Handle responds to revocation requests. It attempts to revoke
// a certificate with a given serial number
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
	var req jsonRevokeRequest
	err = json.Unmarshal(body, &req)
	if err != nil {
		return errors.NewBadRequestString("Unable to parse revocation request")
	}

	if len(req.Serial) == 0 {
		return errors.NewBadRequestString("serial number is required but not provided")
	}

	var reasonCode int
	reasonCode, err = ocsp.ReasonStringToCode(req.Reason)
	if err != nil {
		return errors.NewBadRequestString("Invalid reason code")
	}

	err = h.dbAccessor.RevokeCertificate(req.Serial, req.AKI, reasonCode)
	if err != nil {
		return err
	}

	result := map[string]string{}
	return api.SendResponse(w, result)
}
예제 #2
0
// Handle implements an http.Handler interface for the bundle handler.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) (err error) {
	blob, matched, err := api.ProcessRequestFirstMatchOf(r,
		[][]string{
			[]string{"certificate"},
			[]string{"domain"},
		})
	if err != nil {
		log.Warningf("invalid request: %v", err)
		return err
	}

	var cert *certinfo.Certificate
	switch matched[0] {
	case "domain":
		if cert, err = certinfo.ParseCertificateDomain(blob["domain"]); err != nil {
			log.Warningf("couldn't parse remote certificate: %v", err)
			return err
		}
	case "certificate":
		if cert, err = certinfo.ParseCertificatePEM([]byte(blob["certificate"])); err != nil {
			log.Warningf("bad PEM certifcate: %v", err)
			return err
		}
	}

	return api.SendResponse(w, cert)
}
예제 #3
0
파일: bundle.go 프로젝트: nathany/cfssl
// Handle implements an http.Handler interface for the bundle handler.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
	blob, matched, err := api.ProcessRequestFirstMatchOf(r,
		[][]string{
			{"certificate"},
			{"domain"},
		})
	if err != nil {
		log.Warningf("invalid request: %v", err)
		return err
	}

	flavor := blob["flavor"]
	bf := bundler.Ubiquitous
	if flavor != "" {
		bf = bundler.BundleFlavor(flavor)
	}
	log.Infof("request for flavor %v", bf)

	var result *bundler.Bundle
	switch matched[0] {
	case "domain":
		bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], bf)
		if err != nil {
			log.Warningf("couldn't bundle from remote: %v", err)
			return err
		}
		result = bundle
	case "certificate":
		bundle, err := h.bundler.BundleFromPEMorDER([]byte(blob["certificate"]), []byte(blob["private_key"]), bf, "")
		if err != nil {
			log.Warning("bad PEM certifcate or private key")
			return err
		}

		serverName := blob["domain"]
		ip := blob["ip"]

		if serverName != "" {
			err := bundle.Cert.VerifyHostname(serverName)
			if err != nil {
				return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
			}

		}

		if ip != "" {
			err := bundle.Cert.VerifyHostname(ip)
			if err != nil {
				return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
			}
		}

		result = bundle
	}
	log.Info("wrote response")
	return api.SendResponse(w, result)
}
예제 #4
0
파일: ocspsign.go 프로젝트: jfrazelle/cfssl
// 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)
}
예제 #5
0
// Handle responds to requests for the CA to sign the certificate request
// present in the "certificate_request" parameter for the host named
// in the "hostname" parameter. The certificate should be PEM-encoded. If
// provided, subject information from the "subject" parameter will be used
// in place of the subject information from the CSR.
func (h *SignHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("signature request received")

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	r.Body.Close()

	var req signer.SignRequest
	err = json.Unmarshal(body, &req)
	if err != nil {
		return err
	}

	if len(req.Hosts) == 0 {
		return errors.NewBadRequestString("missing paratmeter 'hosts'")
	}

	if req.Request == "" {
		return errors.NewBadRequestString("missing parameter 'certificate_request'")
	}

	var cert []byte
	var profile *config.SigningProfile

	policy := h.signer.Policy()
	if policy != nil && policy.Profiles != nil && req.Profile != "" {
		profile = policy.Profiles[req.Profile]
	}

	if profile == nil && policy != nil {
		profile = policy.Default
	}

	if profile.Provider != nil {
		log.Error("profile requires authentication")
		return errors.NewBadRequestString("authentication required")
	}

	cert, err = h.signer.Sign(req)
	if err != nil {
		log.Warningf("failed to sign request: %v", err)
		return err
	}

	result := map[string]string{"certificate": string(cert)}
	log.Info("wrote response")
	return api.SendResponse(w, result)
}
예제 #6
0
파일: sign.go 프로젝트: jgeromero/cfssl
// Handle responds to requests for the CA to sign the certificate request
// present in the "certificate_request" parameter for the host named
// in the "hostname" parameter. The certificate should be PEM-encoded. If
// provided, subject information from the "subject" parameter will be used
// in place of the subject information from the CSR.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("signature request received")

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	r.Body.Close()

	var req jsonSignRequest

	err = json.Unmarshal(body, &req)
	if err != nil {
		return errors.NewBadRequestString("Unable to parse sign request")
	}

	signReq := jsonReqToTrue(req)

	if req.Request == "" {
		return errors.NewBadRequestString("missing parameter 'certificate_request'")
	}

	var cert []byte
	profile, err := signer.Profile(h.signer, req.Profile)
	if err != nil {
		return err
	}

	if profile.Provider != nil {
		log.Error("profile requires authentication")
		return errors.NewBadRequestString("authentication required")
	}

	cert, err = h.signer.Sign(signReq)
	if err != nil {
		log.Warningf("failed to sign request: %v", err)
		return err
	}

	result := map[string]string{"certificate": string(cert)}
	log.Info("wrote response")
	return api.SendResponse(w, result)
}
예제 #7
0
// Handle responds to requests for the CA to generate a new private
// key and certificate on behalf of the client. The format for these
// requests is documented in the API documentation.
func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("request for CSR")

	req := new(genSignRequest)
	req.Request = csr.New()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Warningf("failed to read request body: %v", err)
		return errors.NewBadRequest(err)
	}

	err = json.Unmarshal(body, req)
	if err != nil {
		log.Warningf("failed to unmarshal request: %v", err)
		return errors.NewBadRequest(err)
	}

	if req.Request == nil {
		log.Warning("empty request received")
		return errors.NewBadRequestString("missing request section")
	}

	if req.Request.CA != nil {
		log.Warningf("request received with CA section")
		return errors.NewBadRequestString("ca section only permitted in initca")
	}

	csr, key, err := cg.generator.ProcessRequest(req.Request)
	if err != nil {
		log.Warningf("failed to process CSR: %v", err)
		// The validator returns a *cfssl/errors.HttpError
		return err
	}

	signReq := signer.SignRequest{
		Request: string(csr),
		Profile: req.Profile,
		Label:   req.Label,
	}

	certBytes, err := cg.signer.Sign(signReq)
	if err != nil {
		log.Warningf("failed to sign request: %v", err)
		return err
	}

	reqSum, err := computeSum(csr)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	certSum, err := computeSum(certBytes)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	var file string
	if req.Format.Type == "pkcs12" {
		var password []byte
		if req.Format.Password != "" {
			password = []byte(req.Format.Password)
		}
		file = pkcs12.ParseAndEncode(key, certBytes, password)
	}

	result := map[string]interface{}{
		"private_key":         string(key),
		"certificate_request": string(csr),
		"certificate":         string(certBytes),
		"format":              file,
		"sums": map[string]Sum{
			"certificate_request": reqSum,
			"certificate":         certSum,
		},
	}

	if len(req.Request.Hosts) == 0 {
		return api.SendResponseWithMessage(w, result, CSRNoHostMessage,
			errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
	}

	return api.SendResponse(w, result)
}
예제 #8
0
파일: generator.go 프로젝트: 40a/cfssl
// Handle responds to requests for the CA to generate a new private
// key and certificate on behalf of the client. The format for these
// requests is documented in the API documentation.
func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("request for CSR")

	req := new(genSignRequest)
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Warningf("failed to read request body: %v", err)
		return errors.NewBadRequest(err)
	}

	err = json.Unmarshal(body, req)
	if err != nil {
		log.Warningf("failed to unmarshal request: %v", err)
		return errors.NewBadRequest(err)
	}

	if req.Request == nil {
		log.Warning("empty request received")
		return errors.NewBadRequestString("missing request section")
	}

	if req.Request.CA != nil {
		log.Warningf("request received with CA section")
		return errors.NewBadRequestString("ca section only permitted in initca")
	}

	csr, key, err := cg.generator.ProcessRequest(req.Request)
	if err != nil {
		log.Warningf("failed to process CSR: %v", err)
		// The validator returns a *cfssl/errors.HttpError
		return err
	}

	signReq := signer.SignRequest{
		Request: string(csr),
		Profile: req.Profile,
		Label:   req.Label,
	}

	certBytes, err := cg.signer.Sign(signReq)
	if err != nil {
		log.Warningf("failed to sign request: %v", err)
		return err
	}

	reqSum, err := computeSum(csr)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	certSum, err := computeSum(certBytes)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	result := map[string]interface{}{
		"private_key":         string(key),
		"certificate_request": string(csr),
		"certificate":         string(certBytes),
		"sums": map[string]Sum{
			"certificate_request": reqSum,
			"certificate":         certSum,
		},
	}
	return api.SendResponse(w, result)
}
예제 #9
0
파일: sign.go 프로젝트: jgeromero/cfssl
// Handle receives the incoming request, validates it, and processes it.
func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("signature request received")

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Errorf("failed to read response body: %v", err)
		return err
	}
	r.Body.Close()

	var aReq auth.AuthenticatedRequest
	err = json.Unmarshal(body, &aReq)
	if err != nil {
		log.Errorf("failed to unmarshal authenticated request: %v", err)
		return errors.NewBadRequest(err)
	}

	var req jsonSignRequest
	err = json.Unmarshal(aReq.Request, &req)
	if err != nil {
		log.Errorf("failed to unmarshal request from authenticated request: %v", err)
		return errors.NewBadRequestString("Unable to parse authenticated sign request")
	}

	// Sanity checks to ensure that we have a valid policy. This
	// should have been checked in NewAuthHandler.
	policy := h.signer.Policy()
	if policy == nil {
		log.Critical("signer was initialised without a signing policy")
		return errors.NewBadRequestString("invalid policy")
	}

	profile, err := signer.Profile(h.signer, req.Profile)
	if err != nil {
		return err
	}

	if profile.Provider == nil {
		log.Error("profile has no authentication provider")
		return errors.NewBadRequestString("no authentication provider")
	}

	if !profile.Provider.Verify(&aReq) {
		log.Warning("received authenticated request with invalid token")
		return errors.NewBadRequestString("invalid token")
	}

	signReq := jsonReqToTrue(req)

	if signReq.Request == "" {
		return errors.NewBadRequestString("missing parameter 'certificate_request'")
	}

	cert, err := h.signer.Sign(signReq)
	if err != nil {
		log.Errorf("signature failed: %v", err)
		return err
	}

	result := map[string]string{"certificate": string(cert)}
	log.Info("wrote response")
	return api.SendResponse(w, result)
}
예제 #10
0
// Handle responds to requests for crl generation. It creates this crl
// based off of the given certificate, serial numbers, and private key
func crlHandler(w http.ResponseWriter, r *http.Request) error {

	var revokedCerts []pkix.RevokedCertificate
	var oneWeek = time.Duration(604800) * time.Second
	var newExpiryTime = time.Now()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	r.Body.Close()

	req := &jsonCRLRequest{}

	err = json.Unmarshal(body, req)
	if err != nil {
		log.Error(err)
	}

	if req.ExpiryTime != "" {
		expiryTime := strings.TrimSpace(req.ExpiryTime)
		expiryInt, err := strconv.ParseInt(expiryTime, 0, 32)
		if err != nil {
			return err
		}

		newExpiryTime = time.Now().Add((time.Duration(expiryInt) * time.Second))
	}

	if req.ExpiryTime == "" {
		newExpiryTime = time.Now().Add(oneWeek)
	}

	if err != nil {
		return err
	}

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

	for _, value := range req.SerialNumber {
		tempBigInt := new(big.Int)
		tempBigInt.SetString(value, 10)
		tempCert := pkix.RevokedCertificate{
			SerialNumber:   tempBigInt,
			RevocationTime: time.Now(),
		}
		revokedCerts = append(revokedCerts, tempCert)
	}

	key, err := helpers.ParsePrivateKeyPEM([]byte(req.PrivateKey))
	if err != nil {
		log.Debug("Malformed private key %v", err)
		return errors.NewBadRequestString("Malformed Private Key")
	}

	result, err := cert.CreateCRL(rand.Reader, key, revokedCerts, time.Now(), newExpiryTime)

	return api.SendResponse(w, result)
}
예제 #11
0
// Handle responds to requests for the CA to generate a new private
// key and certificate on behalf of the client. The format for these
// requests is documented in the API documentation.
func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("request for CSR")

	req := new(genSignRequest)
	req.Request = csr.New()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Warningf("failed to read request body: %v", err)
		return errors.NewBadRequest(err)
	}
	r.Body.Close()

	err = json.Unmarshal(body, req)
	if err != nil {
		log.Warningf("failed to unmarshal request: %v", err)
		return errors.NewBadRequest(err)
	}

	if req.Request == nil {
		log.Warning("empty request received")
		return errors.NewBadRequestString("missing request section")
	}

	if req.Request.CA != nil {
		log.Warningf("request received with CA section")
		return errors.NewBadRequestString("ca section only permitted in initca")
	}

	csr, key, err := cg.generator.ProcessRequest(req.Request)
	if err != nil {
		log.Warningf("failed to process CSR: %v", err)
		// The validator returns a *cfssl/errors.HttpError
		return err
	}

	signReq := signer.SignRequest{
		Request: string(csr),
		Profile: req.Profile,
		Label:   req.Label,
	}

	certBytes, err := cg.signer.Sign(signReq)
	if err != nil {
		log.Warningf("failed to sign request: %v", err)
		return err
	}

	reqSum, err := computeSum(csr)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	certSum, err := computeSum(certBytes)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	result := map[string]interface{}{
		"private_key":         string(key),
		"certificate_request": string(csr),
		"certificate":         string(certBytes),
		"sums": map[string]Sum{
			"certificate_request": reqSum,
			"certificate":         certSum,
		},
	}

	if req.Bundle {
		if cg.bundler == nil {
			return api.SendResponseWithMessage(w, result, NoBundlerMessage,
				errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
		}

		bundle, err := cg.bundler.BundleFromPEMorDER(certBytes, nil, bundler.Optimal, "")
		if err != nil {
			return err
		}

		result["bundle"] = bundle
	}

	if len(req.Request.Hosts) == 0 {
		return api.SendResponseWithMessage(w, result, CSRNoHostMessage,
			errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
	}

	return api.SendResponse(w, result)
}