Beispiel #1
0
func decodeCertChain(chainPEM string) (chain x509Chain, err error) {
	certPEMBlock := []byte(chainPEM)
	var certDERBlock *pem.Block
	var cert tls.Certificate

	for {
		certDERBlock, certPEMBlock = pem.Decode([]byte(certPEMBlock))
		if certDERBlock == nil {
			break
		}
		if certDERBlock.Type == "CERTIFICATE" {
			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
		}
	}

	if len(cert.Certificate) == 0 {
		err = errors.New("failed to parse certificate PEM data")
		return
	}

	var x509Cert *x509.Certificate
	for _, c := range cert.Certificate {
		x509Cert, err = x509.ParseCertificate(c)
		if err != nil {
			return
		}
		chain = append(chain, *x509Cert)
	}
	return
}
Beispiel #2
0
// FromPemBytes loads a PEM certificate from an in memory byte array and
// returns a tls.Certificate. This function is similar to the crypto/tls
// X509KeyPair function, however it supports PEM files with the cert and
// key combined, as well as password protected keys which are both common with
// APNs certificates.
//
// Use "" as the password argument if the PEM certificate is not password
// protected.
func FromPemBytes(bytes []byte, password string) (tls.Certificate, error) {
	var cert tls.Certificate
	var block *pem.Block
	for {
		block, bytes = pem.Decode(bytes)
		if block == nil {
			break
		}
		if block.Type == "CERTIFICATE" {
			cert.Certificate = append(cert.Certificate, block.Bytes)
		}
		if block.Type == "PRIVATE KEY" || strings.HasSuffix(block.Type, "PRIVATE KEY") {
			key, err := unencryptPrivateKey(block, password)
			if err != nil {
				return tls.Certificate{}, err
			}
			cert.PrivateKey = key
		}
	}
	if len(cert.Certificate) == 0 {
		return tls.Certificate{}, ErrNoCertificate
	}
	if cert.PrivateKey == nil {
		return tls.Certificate{}, ErrNoPrivateKey
	}
	if c, e := x509.ParseCertificate(cert.Certificate[0]); e == nil {
		cert.Leaf = c
	}
	return cert, nil
}
Beispiel #3
0
// Intercepts an SSL connection to a remote server. The request will instead be
// redirected to the socket configured at p.SocketPath.
//
// SSL Added and removed here! :-)
func (p *InterceptingProxyHandler) interceptRequest(w http.ResponseWriter, r *http.Request) {
	log.Println("hijacking TLS connection")

	tlsConn, err := tls.Dial("tcp", r.URL.Host, nil)
	defer tlsConn.Close()

	if err != nil {
		log.Println("error dialing TLS, falling back:", err)
		p.doConnectRequest(w, r)
		return
	}

	cs := tlsConn.ConnectionState()
	peerCerts := cs.PeerCertificates

	fakedCert := tls.Certificate{}
	fakedCert.PrivateKey = p.privateKey

	for _, peerCert := range peerCerts {
		fakedCert.Certificate = append(fakedCert.Certificate, peerCert.Raw)
	}

	host, _, _ := net.SplitHostPort(r.URL.Host)

	config := &tls.Config{
		Certificates:             []tls.Certificate{fakedCert},
		ServerName:               host,
		PreferServerCipherSuites: true,
		CipherSuites:             VulnerableCipherSuites,
		MaxVersion:               tls.VersionTLS11,
	}

	w.WriteHeader(http.StatusOK)

	hijackedConnection, _, err := w.(http.Hijacker).Hijack()
	if err != nil {
		log.Println("error hijacking connection", err)
		return
	}

	serverConn := tls.Server(hijackedConnection, config)

	if err := serverConn.Handshake(); err != nil {
		log.Println("error during handshake:", err)
		return
	}

	interceptorConn, err := net.Dial("unix", p.SocketPath)

	if err != nil {
		log.Println("error dialing socket:", err)
		return
	}

	go io.Copy(serverConn, interceptorConn)
	go io.Copy(interceptorConn, serverConn)
}
Beispiel #4
0
// GetTLSConfig returns a TLS config generally suitable for client
// authentiation. The returned TLS config can be modified slightly
// to be made suitable for a server requiring client authentication;
// specifically, you should set the value of ClientAuth in the returned
// config to match your needs.
func (p *ParsedCertBundle) GetTLSConfig(usage TLSUsage) (*tls.Config, error) {
	tlsCert := tls.Certificate{
		Certificate: [][]byte{},
	}

	tlsConfig := &tls.Config{
		MinVersion: tls.VersionTLS12,
	}

	if p.Certificate != nil {
		tlsCert.Leaf = p.Certificate
	}

	if p.PrivateKey != nil {
		tlsCert.PrivateKey = p.PrivateKey
	}

	if p.CertificateBytes != nil && len(p.CertificateBytes) > 0 {
		tlsCert.Certificate = append(tlsCert.Certificate, p.CertificateBytes)
	}

	if len(p.CAChain) > 0 {
		for _, cert := range p.CAChain {
			tlsCert.Certificate = append(tlsCert.Certificate, cert.Bytes)
		}

		// Technically we only need one cert, but this doesn't duplicate code
		certBundle, err := p.ToCertBundle()
		if err != nil {
			return nil, fmt.Errorf("Error converting parsed bundle to string bundle when getting TLS config: %s", err)
		}

		caPool := x509.NewCertPool()
		ok := caPool.AppendCertsFromPEM([]byte(certBundle.CAChain[0]))
		if !ok {
			return nil, fmt.Errorf("Could not append CA certificate")
		}

		if usage&TLSServer > 0 {
			tlsConfig.ClientCAs = caPool
			tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
		}
		if usage&TLSClient > 0 {
			tlsConfig.RootCAs = caPool
		}
	}

	if tlsCert.Certificate != nil && len(tlsCert.Certificate) > 0 {
		tlsConfig.Certificates = []tls.Certificate{tlsCert}
		tlsConfig.BuildNameToCertificate()
	}

	return tlsConfig, nil
}
Beispiel #5
0
// imitateCertificate returns a new TLS certificate that has most of the same
// data as serverCert but is signed by Redwood's root certificate, or
// self-signed.
func imitateCertificate(serverCert *x509.Certificate, selfSigned bool, conf *config) (cert tls.Certificate, err error) {
	template := serverCert

	if selfSigned {
		template = &x509.Certificate{
			SerialNumber: new(big.Int).SetInt64(0),
			Subject:      serverCert.Subject,
			NotBefore:    serverCert.NotBefore,
			NotAfter:     serverCert.NotAfter,
			KeyUsage:     x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
			ExtKeyUsage:  serverCert.ExtKeyUsage,
			DNSNames:     serverCert.DNSNames,
		}
	} else {
		// Use a hash of the real certificate as the serial number.
		h := md5.New()
		h.Write(serverCert.Raw)
		h.Write([]byte{1}) // To give different serial numbers after the key usage change.
		template.SerialNumber = big.NewInt(0).SetBytes(h.Sum(nil))
		if err != nil {
			return tls.Certificate{}, fmt.Errorf("failed to generate serial number: %s", err)
		}
		template.SubjectKeyId = nil
		template.AuthorityKeyId = nil
		template.OCSPServer = nil
		template.IssuingCertificateURL = nil
		template.CRLDistributionPoints = nil
		template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
		template.BasicConstraintsValid = false
		template.SignatureAlgorithm = x509.UnknownSignatureAlgorithm
	}

	var newCertBytes []byte
	if selfSigned {
		newCertBytes, err = x509.CreateCertificate(rand.Reader, template, template, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey)
	} else {
		newCertBytes, err = x509.CreateCertificate(rand.Reader, template, conf.ParsedTLSCert, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey)
	}
	if err != nil {
		return tls.Certificate{}, err
	}

	newCert := tls.Certificate{
		Certificate: [][]byte{newCertBytes},
		PrivateKey:  conf.TLSCert.PrivateKey,
	}

	if !selfSigned {
		newCert.Certificate = append(newCert.Certificate, conf.TLSCert.Certificate...)
	}
	return newCert, nil
}
Beispiel #6
0
func (uh *UsersCertificateHandler) Get(request *http.Request) (userid string, err error) {
	if uh.verifiedHeader != "" && uh.verifiedHeaderValue != "" {
		// Use incoming HTTP headers.
		if request.Header.Get(uh.verifiedHeader) != uh.verifiedHeaderValue {
			// Verify header does not match - ignore incoming userid.
			return
		}
		if uh.certificateHeader != "" {
			// Read userid from certificate in header if configured.
			var cert tls.Certificate
			var certDERBlock *pem.Block
			// Whuahah this is an evil fix to get back valid PEM data from Nginx $ssl_client_cert values.
			certString := strings.Replace(request.Header.Get(uh.certificateHeader), " ", "\n", -1)
			certString = strings.Replace(certString, "BEGIN\n", "BEGIN ", 1)
			certString = strings.Replace(certString, "END\n", "END ", 1)
			certPEMBlock := []byte(certString)
			for {
				certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
				if certDERBlock == nil {
					break
				}
				if certDERBlock.Type == "CERTIFICATE" {
					cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
				}
			}
			if len(cert.Certificate) == 0 {
				err = errors.New("failed to parse certificate PEM data")
				return
			}
			var certificates []*x509.Certificate
			if certificates, err = x509.ParseCertificates(cert.Certificate[0]); err == nil {
				userid = certificates[0].Subject.CommonName
			}
		}
	} else {
		// Direct TLS termination and authentication.
		if request.TLS == nil || len(request.TLS.VerifiedChains) == 0 {
			return
		}
		chain := request.TLS.VerifiedChains[0]
		if len(chain) == 0 {
			return
		}
		cert := chain[0]
		userid = cert.Subject.CommonName
	}
	log.Printf("Client certificate found for user: %s\n", userid)
	return
}
Beispiel #7
0
Datei: x509.go Projekt: Zyko0/cli
func decodePem(certInput string) tls.Certificate {
	var cert tls.Certificate
	certPEMBlock := []byte(certInput)
	var certDERBlock *pem.Block
	for {
		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
		if certDERBlock == nil {
			break
		}
		if certDERBlock.Type == "CERTIFICATE" {
			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
		}
	}
	return cert
}
Beispiel #8
0
// Include our root certificate in TLS.
//
// THIS IS A MODIFICATION TO THE ORIGINAL
// VERSION OF THE SOURCE CODE.
// CHANGED ON SEPTEMBER 05, 2013
//
// This builds on the gist available at:
// https://gist.github.com/laher/5795578
// and is meant to resolve the error:
// "x509: failed to load system roots and no roots provided"
// This happens since cross-compiling disables cgo -
// however cgo is required to find system root
// certificates on darwin machines. Note that the client
// returned can only connect successfully to the
// supplied s3's region.
func getHttpClient(s3 *S3) (*http.Client, error) {
	// get the pem string by running openssl. Note that the
	// endpoint will only work for the regional s3 endpoint
	// supplied
	out, err := exec.Command("openssl", "s_client", "-showcerts", "-connect", strings.Replace(s3.Region.S3Endpoint, "https://", "", -1)+":443").Output()
	if err != nil {
		return nil, err
	}
	certInput := string(out)

	// decode the pem string returned by openssl
	var certChain tls.Certificate
	certPEMBlock := []byte(certInput)
	var certDERBlock *pem.Block
	for {
		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
		if certDERBlock == nil {
			break
		}
		if certDERBlock.Type == "CERTIFICATE" {
			certChain.Certificate = append(certChain.Certificate, certDERBlock.Bytes)
		}
	}

	// inititalize our tls certificate config
	conf := tls.Config{}

	// we're creating a new cert pool here
	// to use for TLS
	conf.RootCAs = x509.NewCertPool()
	for _, cert := range certChain.Certificate {
		x509Cert, err := x509.ParseCertificate(cert)
		if err != nil {
			return nil, err
		}
		conf.RootCAs.AddCert(x509Cert)
	}

	// map certificate names to actual certificates
	conf.BuildNameToCertificate()

	// create a Transport which inlcudes our TLS config
	tr := http.Transport{TLSClientConfig: &conf}

	// add the Transport to our http client
	return &http.Client{Transport: &tr}, nil
}
Beispiel #9
0
func loadCertificate() (tls.Certificate, error) {
	if *p12File != "" {
		cert := tls.Certificate{}
		b, err := ioutil.ReadFile(*p12File)
		if err != nil {
			return cert, err
		}
		key, cer, err := pkcs12.Decode(b, *p12Password)
		if err != nil {
			return cert, err
		}
		cert.PrivateKey = key
		cert.Certificate = [][]byte{cer.Raw}
		return cert, nil
	} else {
		return tls.LoadX509KeyPair(*cerFile, *keyFile)
	}
}
Beispiel #10
0
// imitateCertificate returns a new TLS certificate that has most of the same
// data as serverCert but is signed by Redwood's root certificate, or
// self-signed.
func imitateCertificate(serverCert *x509.Certificate, selfSigned bool, conf *config) (cert tls.Certificate, err error) {
	// Use a hash of the real certificate as the serial number.
	h := md5.New()
	h.Write(serverCert.Raw)
	h.Write([]byte{2})

	template := &x509.Certificate{
		SerialNumber:                big.NewInt(0).SetBytes(h.Sum(nil)),
		Subject:                     serverCert.Subject,
		NotBefore:                   serverCert.NotBefore,
		NotAfter:                    serverCert.NotAfter,
		KeyUsage:                    x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:                 serverCert.ExtKeyUsage,
		UnknownExtKeyUsage:          serverCert.UnknownExtKeyUsage,
		BasicConstraintsValid:       false,
		SubjectKeyId:                nil,
		DNSNames:                    serverCert.DNSNames,
		PermittedDNSDomainsCritical: serverCert.PermittedDNSDomainsCritical,
		PermittedDNSDomains:         serverCert.PermittedDNSDomains,
		SignatureAlgorithm:          x509.UnknownSignatureAlgorithm,
	}

	var newCertBytes []byte
	if selfSigned {
		newCertBytes, err = x509.CreateCertificate(rand.Reader, template, template, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey)
	} else {
		newCertBytes, err = x509.CreateCertificate(rand.Reader, template, conf.ParsedTLSCert, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey)
	}
	if err != nil {
		return tls.Certificate{}, err
	}

	newCert := tls.Certificate{
		Certificate: [][]byte{newCertBytes},
		PrivateKey:  conf.TLSCert.PrivateKey,
	}

	if !selfSigned {
		newCert.Certificate = append(newCert.Certificate, conf.TLSCert.Certificate...)
	}
	return newCert, nil
}