Пример #1
0
// NewBundler creates a new Bundler from the files passed in; these
// files should contain a list of valid root certificates and a list
// of valid intermediate certificates, respectively.
func NewBundler(caBundleFile, intBundleFile string) (*Bundler, error) {
	log.Debug("Loading CA bundle: ", caBundleFile)
	caBundle, err := ioutil.ReadFile(caBundleFile)
	if err != nil {
		log.Errorf("root bundle failed to load: %v", err)
		return nil, errors.Wrap(errors.RootError, errors.ReadFailed, err)
	}

	log.Debug("Loading Intermediate bundle: ", intBundleFile)
	intBundle, err := ioutil.ReadFile(intBundleFile)
	if err != nil {
		log.Errorf("intermediate bundle failed to load: %v", err)
		return nil, errors.Wrap(errors.IntermediatesError, errors.ReadFailed, err)
	}

	if _, err := os.Stat(IntermediateStash); err != nil && os.IsNotExist(err) {
		log.Infof("intermediate stash directory %s doesn't exist, creating", IntermediateStash)
		err = os.MkdirAll(IntermediateStash, 0755)
		if err != nil {
			log.Errorf("failed to create intermediate stash directory %s: %v",
				IntermediateStash, err)
			return nil, err
		}
		log.Infof("intermediate stash directory %s created", IntermediateStash)
	}
	return NewBundlerFromPEM(caBundle, intBundle)

}
Пример #2
0
// VerifyCertificate ensures that the certificate passed in hasn't
// expired and checks the CRL for the server.
func VerifyCertificate(cert *x509.Certificate) (revoked, ok bool) {
	if !time.Now().Before(cert.NotAfter) {
		log.Infof("Certificate expired %s\n", cert.NotAfter)
		return true, true
	} else if !time.Now().After(cert.NotBefore) {
		log.Infof("Certificate isn't valid until %s\n", cert.NotBefore)
		return true, true
	}

	return revCheck(cert)
}
Пример #3
0
func initializeServer() *server.Server {
	var hosts string
	fmt.Print("Keyserver Hostnames/IPs (comma-seperated): ")
	fmt.Scanln(&hosts)
	hostnames := strings.Split(hosts, ",")

	csr, key, err := csr.ParseRequest(&csr.CertificateRequest{
		CN:    "Keyless Server Authentication Certificate",
		Hosts: hostnames,
		KeyRequest: &csr.BasicKeyRequest{
			A: "ecdsa",
			S: 384,
		},
	})
	if err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile(keyFile, key, 0400); err != nil {
		log.Fatal(err)
	}
	log.Infof("Key generated and saved to %s\n", keyFile)

	log.Info("Server entering initialization state")
	s, err := server.NewServerFromFile(initCertFile, initKeyFile, caFile,
		net.JoinHostPort("", port), net.JoinHostPort("", metricsPort))
	if err != nil {
		log.Fatal(err)
	}
	s.ActivationToken = []byte(initToken)
	go func() {
		log.Fatal(s.ListenAndServe())
	}()

	cert, err := initAPICall(hostnames, string(csr))
	if err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile(certFile, cert, 0644); err != nil {
		log.Fatal(err)
	}
	log.Infof("Cert saved to %s\n", certFile)

	// Remove server from activation state and initialize issued certificate.
	s.ActivationToken = s.ActivationToken[:0]
	tlsCert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		log.Fatal(err)
	}

	s.Config.Certificates = []tls.Certificate{tlsCert}
	return s
}
Пример #4
0
// SignerFromConfigAndDB takes the Config and creates the appropriate
// signer.Signer object with a specified db
func SignerFromConfigAndDB(c cli.Config, db *sqlx.DB) (signer.Signer, error) {
	// If there is a config, use its signing policy. Otherwise create a default policy.
	var policy *config.Signing
	if c.CFG != nil {
		policy = c.CFG.Signing
	} else {
		policy = &config.Signing{
			Profiles: map[string]*config.SigningProfile{},
			Default:  config.DefaultConfig(),
		}
	}

	// Make sure the policy reflects the new remote
	if c.Remote != "" {
		err := policy.OverrideRemotes(c.Remote)
		if err != nil {
			log.Infof("Invalid remote %v, reverting to configuration default", c.Remote)
			return nil, err
		}
	}

	if c.MutualTLSCertFile != "" && c.MutualTLSKeyFile != "" {
		err := policy.SetClientCertKeyPairFromFile(c.MutualTLSCertFile, c.MutualTLSKeyFile)
		if err != nil {
			log.Infof("Invalid mutual-tls-cert: %s or mutual-tls-key: %s, defaulting to no client auth", c.MutualTLSCertFile, c.MutualTLSKeyFile)
			return nil, err
		}
		log.Infof("Using client auth with mutual-tls-cert: %s and mutual-tls-key: %s", c.MutualTLSCertFile, c.MutualTLSKeyFile)
	}

	if c.TLSRemoteCAs != "" {
		err := policy.SetRemoteCAsFromFile(c.TLSRemoteCAs)
		if err != nil {
			log.Infof("Invalid tls-remote-ca: %s, defaulting to system trust store", c.TLSRemoteCAs)
			return nil, err
		}
		log.Infof("Using trusted CA from tls-remote-ca: %s", c.TLSRemoteCAs)
	}

	s, err := universal.NewSigner(cli.RootFromConfig(&c), policy)
	if err != nil {
		return nil, err
	}

	if db != nil {
		dbAccessor := certsql.NewAccessor(db)
		s.SetDBAccessor(dbAccessor)
	}

	return s, nil
}
Пример #5
0
// worker does all the parsing and validation of the certificate(s)
// contained in a single file. It first reads all the data in the
// file, then begins parsing certificates in the file. Those
// certificates are then checked for revocation.
func worker(paths chan string, bundler chan *x509.Certificate, pool *sync.WaitGroup) {
	defer (*pool).Done()
	for {
		path, ok := <-paths
		if !ok {
			return
		}

		log.Infof("Loading %s", path)

		fileData, err := ioutil.ReadFile(path)
		if err != nil {
			log.Warningf("%v", err)
			continue
		}

		for {
			var block *pem.Block
			if len(fileData) == 0 {
				break
			}
			block, fileData = pem.Decode(fileData)
			if block == nil {
				log.Warningf("%s: no PEM data found", path)
				break
			} else if block.Type != "CERTIFICATE" {
				log.Info("Skipping non-certificate")
				continue
			}

			cert, err := x509.ParseCertificate(block.Bytes)
			if err != nil {
				log.Warningf("Invalid certificate: %v", err)
				continue
			}

			log.Infof("Validating %+v", cert.Subject)
			revoked, ok := revoke.VerifyCertificate(cert)
			if !ok {
				log.Warning("Failed to verify certificate.")
			} else if !revoked {
				bundler <- cert
			} else {
				log.Info("Skipping revoked certificate")
			}
		}
	}
}
Пример #6
0
// makeBundle opens the file for writing, and listens for incoming
// certificates. These are PEM-encoded and written to file.
func makeBundle(filename string, bundler chan *x509.Certificate) {
	file, err := os.Create(filename)
	if err != nil {
		log.Errorf("%v", err)
		return
	}
	defer file.Close()

	var total int
	for {
		cert, ok := <-bundler
		if !ok {
			break
		}
		block := &pem.Block{
			Type:  "CERTIFICATE",
			Bytes: cert.Raw,
		}
		err = pem.Encode(file, block)
		if err != nil {
			log.Errorf("Failed to write PEM block: %v", err)
			break
		}
		total++
	}
	log.Infof("Wrote %d certificates.", total)
}
Пример #7
0
// NewFromSigner creates a new root certificate from a crypto.Signer.
func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) {
	policy := CAPolicy()
	if req.CA != nil {
		if req.CA.Expiry != "" {
			policy.Default.ExpiryString = req.CA.Expiry
			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
			if err != nil {
				return nil, nil, err
			}
		}

		signer.MaxPathLen = req.CA.PathLength
		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
			log.Infof("ignore invalid 'pathlenzero' value")
		} else {
			signer.MaxPathLenZero = req.CA.PathLenZero
		}
	}

	csrPEM, err = csr.Generate(priv, req)
	if err != nil {
		return nil, nil, err
	}

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}
	s.SetPolicy(policy)

	signReq := signer.SignRequest{Request: string(csrPEM)}
	cert, err = s.Sign(signReq)
	return
}
Пример #8
0
// revCheck should check the certificate for any revocations. It
// returns a pair of booleans: the first indicates whether the certificate
// is revoked, the second indicates whether the revocations were
// successfully checked.. This leads to the following combinations:
//
//  false, false: an error was encountered while checking revocations.
//
//  false, true:  the certificate was checked successfully and
//                  it is not revoked.
//
//  true, true:   the certificate was checked successfully and
//                  it is revoked.
//
//  true, false:  failure to check revocation status causes
//                  verification to fail
func revCheck(cert *x509.Certificate) (revoked, ok bool) {
	for _, url := range cert.CRLDistributionPoints {
		if ldapURL(url) {
			log.Infof("skipping LDAP CRL: %s", url)
			continue
		}

		if revoked, ok := certIsRevokedCRL(cert, url); !ok {
			log.Warning("error checking revocation via CRL")
			if HardFail {
				return true, false
			}
			return false, false
		} else if revoked {
			log.Info("certificate is revoked via CRL")
			return true, true
		}

		if revoked, ok := certIsRevokedOCSP(cert, HardFail); !ok {
			log.Warning("error checking revocation via OCSP")
			if HardFail {
				return true, false
			}
			return false, false
		} else if revoked {
			log.Info("certificate is revoked via OCSP")
			return true, true
		}
	}

	return false, true
}
Пример #9
0
// LoadPlatforms reads the file content as a json object array and convert it
// to Platforms.
func LoadPlatforms(filename string) {
	// Attempt to load root certificate metadata
	log.Debug("Loading platform metadata: ", filename)
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Errorf("platform metadata failed to load: %v", err)
	}
	var rawPlatforms []Platform
	if bytes != nil {
		err = json.Unmarshal(bytes, &rawPlatforms)
		if err != nil {
			log.Errorf("platform metadata failed to parse: %v", err)
		}
	}

	for _, platform := range rawPlatforms {
		ok := platform.ParseAndLoad()
		if !ok {
			log.Errorf("fail to finalize the parsing of platform metadata:", err)
		} else {
			log.Infof("Platform metadata is loaded: %v %v", platform.Name, len(platform.KeyStore))
			Platforms = append(Platforms, platform)
		}
	}
}
Пример #10
0
// LoadPlatforms reads the file content as a json object array and convert it
// to Platforms.
func LoadPlatforms(filename string) error {
	relativePath := filepath.Dir(filename)
	// Attempt to load root certificate metadata
	log.Debug("Loading platform metadata: ", filename)
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return fmt.Errorf("platform metadata failed to load: %v", err)
	}
	var rawPlatforms []Platform
	if bytes != nil {
		err = json.Unmarshal(bytes, &rawPlatforms)
		if err != nil {
			return fmt.Errorf("platform metadata failed to parse: %v", err)
		}
	}

	for _, platform := range rawPlatforms {
		if platform.KeyStoreFile != "" {
			platform.KeyStoreFile = path.Join(relativePath, platform.KeyStoreFile)
		}
		ok := platform.ParseAndLoad()
		if !ok {
			// erase all loaded platforms
			Platforms = nil
			return fmt.Errorf("fail to finalize the parsing of platform metadata: %v", platform)
		}

		log.Infof("Platform metadata is loaded: %v %v", platform.Name, len(platform.KeyStore))
		Platforms = append(Platforms, platform)
	}

	return nil
}
Пример #11
0
// NewSourceFromFile reads the named file into an InMemorySource.
// The file read by this function must contain whitespace-separated OCSP
// responses. Each OCSP response must be in base64-encoded DER form (i.e.,
// PEM without headers or whitespace).  Invalid responses are ignored.
// This function pulls the entire file into an InMemorySource.
func NewSourceFromFile(responseFile string) (Source, error) {
	fileContents, err := ioutil.ReadFile(responseFile)
	if err != nil {
		return nil, err
	}

	responsesB64 := regexp.MustCompile("\\s").Split(string(fileContents), -1)
	src := InMemorySource{}
	for _, b64 := range responsesB64 {
		// if the line/space is empty just skip
		if b64 == "" {
			continue
		}
		der, tmpErr := base64.StdEncoding.DecodeString(b64)
		if tmpErr != nil {
			log.Errorf("Base64 decode error on: %s", b64)
			continue
		}

		response, tmpErr := ocsp.ParseResponse(der, nil)
		if tmpErr != nil {
			log.Errorf("OCSP decode error on: %s", b64)
			continue
		}

		src[response.SerialNumber.String()] = der
	}

	log.Infof("Read %d OCSP responses", len(src))
	return src, nil
}
Пример #12
0
// SignerFromConfigAndDB takes the Config and creates the appropriate
// signer.Signer object with a specified db
func SignerFromConfigAndDB(c cli.Config, db *sql.DB) (signer.Signer, error) {
	// If there is a config, use its signing policy. Otherwise create a default policy.
	var policy *config.Signing
	if c.CFG != nil {
		policy = c.CFG.Signing
	} else {
		policy = &config.Signing{
			Profiles: map[string]*config.SigningProfile{},
			Default:  config.DefaultConfig(),
		}
	}

	// Make sure the policy reflects the new remote
	if c.Remote != "" {
		err := policy.OverrideRemotes(c.Remote)
		if err != nil {
			log.Infof("Invalid remote %v, reverting to configuration default", c.Remote)
			return nil, err
		}
	}

	s, err := universal.NewSigner(cli.RootFromConfig(&c), policy)
	if err != nil {
		return nil, err
	}

	s.SetDB(db)

	return s, nil
}
Пример #13
0
// Handle accepts client information requests, and uses the label to
// look up the signer whose public certificate should be retrieved. If
// the label is empty, the default label is used.
func (h *MultiHandler) Handle(w http.ResponseWriter, r *http.Request) error {
	req := new(info.Req)
	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)
	}

	log.Debug("checking label")
	if req.Label == "" {
		req.Label = h.defaultLabel
	}

	if _, ok := h.signers[req.Label]; !ok {
		log.Warningf("request for invalid endpoint")
		return errors.NewBadRequestString("bad label")
	}

	log.Debug("getting info")
	resp, err := h.signers[req.Label].Info(*req)
	if err != nil {
		log.Infof("error getting certificate: %v", err)
		return err
	}

	response := api.NewSuccessResponse(resp)
	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	return enc.Encode(response)
}
Пример #14
0
// Scan performs the scan to be performed on the given host and stores its result.
func (s *Scanner) Scan(host string) (Grade, Output, error) {
	grade, output, err := s.scan(host)
	if err != nil {
		log.Infof("scan: %v", err)
		return grade, output, err
	}
	return grade, output, err
}
Пример #15
0
func (stats *statistics) ListenAndServe(addr string) {
	http.HandleFunc("/metrics", stats.serveJSON)
	http.HandleFunc("/metrics.js", stats.serveJSON)
	http.HandleFunc("/metrics.json", stats.serveJSON)

	log.Infof("Serving metrics endpoint at %s/metrics\n", addr)
	log.Critical(http.ListenAndServe(addr, nil))
}
Пример #16
0
// A Responder can process both GET and POST requests.  The mapping
// from an OCSP request to an OCSP response is done by the Source;
// the Responder simply decodes the request, and passes back whatever
// response is provided by the source.
func (rs Responder) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	// Read response from request
	var requestBody []byte
	var err error
	switch request.Method {
	case "GET":
		re := regexp.MustCompile("^.*/")
		base64Request := re.ReplaceAllString(request.RequestURI, "")
		base64Request, err = url.QueryUnescape(base64Request)
		if err != nil {
			return
		}
		requestBody, err = base64.StdEncoding.DecodeString(base64Request)
		if err != nil {
			return
		}
	case "POST":
		requestBody, err = ioutil.ReadAll(request.Body)
		if err != nil {
			response.WriteHeader(http.StatusBadRequest)
			return
		}
	default:
		response.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	// TODO log request
	b64Body := base64.StdEncoding.EncodeToString(requestBody)
	log.Infof("Received OCSP request: %s", b64Body)

	// All responses after this point will be OCSP.
	// We could check for the content type of the request, but that
	// seems unnecessariliy restrictive.
	response.Header().Add("Content-Type", "application/ocsp-response")

	// Parse response as an OCSP request
	// XXX: This fails if the request contains the nonce extension.
	//      We don't intend to support nonces anyway, but maybe we
	//      should return unauthorizedRequest instead of malformed.
	ocspRequest, err := ocsp.ParseRequest(requestBody)
	if err != nil {
		log.Errorf("Error decoding request body: %s", b64Body)
		response.Write(malformedRequestErrorResponse)
		return
	}

	// Look up OCSP response from source
	ocspResponse, found := rs.Source.Response(ocspRequest)
	if !found {
		log.Errorf("No response found for request: %s", b64Body)
		response.Write(unauthorizedErrorResponse)
		return
	}

	// Write OCSP response to response
	response.WriteHeader(http.StatusOK)
	response.Write(ocspResponse)
}
Пример #17
0
// 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)
}
Пример #18
0
func (g *group) Dial(c *Client) (conn *gokeyless.Conn, err error) {
	g.Lock()
	defer g.Unlock()

	if g.Len() == 0 {
		err = errors.New("remote group empty")
		return
	}

	var i *item
	var popped []*item
	for g.Len() > 0 {
		i = heap.Pop(g).(*item)
		popped = append(popped, i)
		if conn, err = i.Dial(c); err == nil {
			break
		}

		i.p = 0
		i.errs = append(i.errs, err)
	}

	for _, f := range popped {
		heap.Push(g, f)
	}

	if err != nil {
		return
	}

	go func() {
		defer conn.Close()
		for {
			start := time.Now()
			err := conn.Ping(nil)
			duration := time.Since(start)

			g.Lock()
			if err != nil {
				i.p = 0
				i.errs = append(i.errs, err)
			} else {
				i.p.Update(1 / float64(duration))
			}
			heap.Fix(g, i.index)
			g.Unlock()

			if err != nil {
				log.Infof("Ping failed: %v", err)
				return
			}

			time.Sleep(time.Minute)
		}
	}()
	return
}
Пример #19
0
// ListenAndServe listens on the TCP network address s.Addr and then
// calls Serve to handle requests on incoming keyless connections.
func (s *Server) ListenAndServe() error {
	l, err := net.Listen("tcp", s.Addr)
	if err != nil {
		return err
	}

	log.Infof("Listenting at %s\n", l.Addr())

	return s.Serve(l)
}
Пример #20
0
Файл: api.go Проект: kalw/cfssl
// ServeHTTP encapsulates the call to underlying Handler to handle the request
// and return the response with proper HTTP status code
func (h HttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	// Throw 405 when requested with an unsupported verb.
	if r.Method != h.Method {
		err = errors.NewMethodNotAllowed(r.Method)
	} else {
		err = h.Handle(w, r)
	}
	status := handleError(w, err)
	log.Infof("%s - \"%s %s\" %d", r.RemoteAddr, r.Method, r.URL, status)
}
Пример #21
0
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
func registerHandlers() {
	for path, getHandler := range v1Endpoints {
		path = "/api/v1/cfssl/" + path
		log.Infof("Setting up '%s' endpoint", path)
		if handler, err := getHandler(); err != nil {
			log.Warningf("endpoint '%s' is disabled: %v", path, err)
		} else {
			http.Handle(path, handler)
		}
	}
	for path, getHandler := range staticEndpoints {
		log.Infof("Setting up '%s' endpoint", path)
		if handler, err := getHandler(); err != nil {
			log.Warningf("endpoint '%s' is disabled: %v", path, err)
		} else {
			http.Handle(path, handler)
		}
	}

	log.Info("Handler set up complete.")
}
Пример #22
0
// RunServerTests load tests a server with a given number of workers and ammount of time.
func RunServerTests(testLen time.Duration, workers int, c *client.Client, server string, privkeys []*client.PrivateKey) {
	log.Infof("Testing %s and %d keys for %v with %d workers...", server, len(privkeys), testLen, workers)

	running := make(chan bool, workers)
	errs := make(chan error)

	for i := 0; i < workers; i++ {
		running <- true
		go func() {
			for range running {
				errs <- testConnect(c, server)

				for _, priv := range privkeys {
					errs <- testKey(priv)
				}

				running <- true
			}
		}()
	}

	timeout := time.After(testLen)
	var testCount, errCount int
	for {
		select {
		case err := <-errs:
			testCount++
			fmt.Print(".")
			if err != nil {
				log.Error(err)
				errCount++
			}

		case <-timeout:
			close(running)
			log.Infof("Completed with %d errors / %d tests", errCount, testCount)
			return
		}
	}
}
Пример #23
0
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
func registerHandlers() {
	for path, getHandler := range endpoints {
		path = v1APIPath(path)
		log.Infof("Setting up '%s' endpoint", path)
		if handler, err := getHandler(); err != nil {
			log.Warningf("endpoint '%s' is disabled: %v", path, err)
		} else {
			http.Handle(path, handler)
		}
	}

	log.Info("Handler set up complete.")
}
Пример #24
0
func (keys *defaultKeystore) Get(op *gokeyless.Operation) (priv crypto.Signer, ok bool) {
	keys.RLock()
	defer keys.RUnlock()

	ski := op.SKI
	if ski.Valid() {
		priv, ok = keys.skis[ski]
	} else {
		if !ok {
			log.Debug("Couldn't look up key based on SKI, trying Digest.")
			if ski, ok = keys.digests[op.Digest]; ok {
				priv, ok = keys.skis[ski]
			}
		}

		if !ok {
			log.Debug("Couldn't look up key based on Digest, trying SNI.")
			if ski, ok = keys.snis[op.SNI]; ok {
				priv, ok = keys.skis[ski]
			}
		}

		if !ok {
			if op.ServerIP != nil {
				log.Debug("Couldn't look up key based on SNI, trying Server IP.")
				if ski, ok = keys.serverIPs[op.ServerIP.String()]; ok {
					priv, ok = keys.skis[ski]
				}
			}
		}

		if !ok {
			if op.ClientIP != nil {
				log.Debug("Couldn't look up key based on Server IP, trying Client IP.")
				if ski, ok = keys.clientIPs[op.ClientIP.String()]; ok {
					priv, ok = keys.skis[ski]
				}
			}
		}
	}

	if !ok {
		log.Infof("Couldn't look up key for %s.", op)
	} else if len(keys.validAKIs[ski]) > 0 && !keys.validAKIs[ski].Contains(op.AKI) {
		log.Warningf("Attempt to access key with invalid AKI: %s", op.AKI)
		return nil, false
	}

	return
}
Пример #25
0
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
func registerHandlers() {
	for path, getHandler := range endpoints {
		log.Debugf("getHandler for %s", path)
		if handler, err := getHandler(); err != nil {
			log.Warningf("endpoint '%s' is disabled: %v", path, err)
		} else {
			if path, handler, err = wrapHandler(path, handler, err); err != nil {
				log.Warningf("endpoint '%s' is disabled by wrapper: %v", path, err)
			} else {
				log.Infof("endpoint '%s' is enabled", path)
				http.Handle(path, handler)
			}
		}
	}
	log.Info("Handler set up complete.")
}
Пример #26
0
// ServeHTTP encapsulates the call to underlying Handler to handle the request
// and return the response with proper HTTP status code
func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	var match bool
	// Throw 405 when requested with an unsupported verb.
	for _, m := range h.Methods {
		if m == r.Method {
			match = true
		}
	}
	if match {
		err = h.Handle(w, r)
	} else {
		err = errors.NewMethodNotAllowed(r.Method)
	}
	status := HandleError(w, err)
	log.Infof("%s - \"%s %s\" %d", r.RemoteAddr, r.Method, r.URL, status)
}
Пример #27
0
// New creates a new root certificate from the certificate request.
func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
	policy := CAPolicy()
	if req.CA != nil {
		if req.CA.Expiry != "" {
			policy.Default.ExpiryString = req.CA.Expiry
			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
			if err != nil {
				return
			}
		}

		policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
			log.Infof("ignore invalid 'pathlenzero' value")
		} else {
			policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
		}
	}

	g := &csr.Generator{Validator: validator}
	csrPEM, key, err = g.ProcessRequest(req)
	if err != nil {
		log.Errorf("failed to process request: %v", err)
		key = nil
		return
	}

	priv, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return
	}

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}

	signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
	cert, err = s.Sign(signReq)

	return

}
Пример #28
0
// ParseRequest takes a certificate request and generates a key and
// CSR from it. It does no validation -- caveat emptor. It will,
// however, fail if the key request is not valid (i.e., an unsupported
// curve or RSA key size). The lack of validation was specifically
// chosen to allow the end user to define a policy and validate the
// request appropriately before calling this function.
func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
	log.Info("received CSR")
	if req.KeyRequest == nil {
		req.KeyRequest = NewBasicKeyRequest()
	}

	log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size())
	priv, err := req.KeyRequest.Generate()
	if err != nil {
		err = cferr.Wrap(cferr.PrivateKeyError, cferr.GenerationFailed, err)
		return
	}

	switch priv := priv.(type) {
	case *rsa.PrivateKey:
		key = x509.MarshalPKCS1PrivateKey(priv)
		block := pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: key,
		}
		key = pem.EncodeToMemory(&block)
	case *ecdsa.PrivateKey:
		key, err = x509.MarshalECPrivateKey(priv)
		if err != nil {
			err = cferr.Wrap(cferr.PrivateKeyError, cferr.Unknown, err)
			return
		}
		block := pem.Block{
			Type:  "EC PRIVATE KEY",
			Bytes: key,
		}
		key = pem.EncodeToMemory(&block)
	default:
		panic("Generate should have failed to produce a valid key.")
	}

	csr, err = Generate(priv.(crypto.Signer), req)
	if err != nil {
		log.Errorf("failed to generate a CSR: %v", err)
		err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
	}
	return
}
Пример #29
0
// RegisterDir reads all .pubkey and .crt files from a directory and returns associated PublicKey structs.
func (c *Client) RegisterDir(server, dir string, LoadPubKey func([]byte) (crypto.PublicKey, error)) (privkeys []*PrivateKey, err error) {
	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		isPubKey := pubkeyExt.MatchString(info.Name())
		isCert := crtExt.MatchString(info.Name())
		if !info.IsDir() && (isPubKey || isCert) {
			log.Infof("Loading %s...\n", path)

			var in []byte
			if in, err = ioutil.ReadFile(path); err != nil {
				return err
			}

			var priv *PrivateKey
			if isPubKey {
				var pub crypto.PublicKey
				if pub, err = LoadPubKey(in); err != nil {
					return err
				}

				if priv, err = c.RegisterPublicKey(server, pub); err != nil {
					return err
				}
			} else {
				var cert *x509.Certificate
				if cert, err = helpers.ParseCertificatePEM(in); err != nil {
					return err
				}

				if priv, err = c.RegisterCert(server, cert); err != nil {
					return err
				}
			}
			privkeys = append(privkeys, priv)
		}
		return nil
	})
	return
}
Пример #30
0
// scanFiles walks the files listed in the arguments. These files may
// be either certificate files or directories containing certificates.
func scanFiles(paths chan string) {
	walker := func(path string, info os.FileInfo, err error) error {
		log.Infof("Found %s", path)
		if err != nil {
			return err
		}

		if info.Mode().IsRegular() {
			paths <- path
		}
		return nil
	}

	for _, path := range flag.Args() {
		err := filepath.Walk(path, walker)
		if err != nil {
			log.Errorf("Walk failed: %v", err)
		}
	}
	close(paths)
}