Beispiel #1
0
// NewTLSConfig returns an initialized TLS configuration suitable for client
// authentication. If caFile is non-empty, it will be loaded.
func NewTLSConfig(caFile string, mutualTLS bool) (*tls.Config, error) {
	var c tls.Config

	// TLS 1.0 at a minimum (for mysql)
	c.MinVersion = tls.VersionTLS10
	c.PreferServerCipherSuites = true

	if mutualTLS {
		log.Info("MutualTLS requested, client certificates will be verified")
		c.ClientAuth = tls.VerifyClientCertIfGiven
	}
	if caFile != "" {
		data, err := ioutil.ReadFile(caFile)
		if err != nil {
			return &c, err
		}
		c.ClientCAs = x509.NewCertPool()
		if !c.ClientCAs.AppendCertsFromPEM(data) {
			return &c, errors.New("No certificates parsed")
		}
		log.Info("Read in CA file:", caFile)
	}
	c.BuildNameToCertificate()
	return &c, nil
}
Beispiel #2
0
// SecureCiphers updates a *tls.Config with a secure ciphersuite configuration.
// If c is nil, a new config will be provided.
func SecureCiphers(c *tls.Config) *tls.Config {
	if c == nil {
		c = &tls.Config{}
	}

	c.MinVersion = tls.VersionTLS10 // disable SSLv3
	c.MaxVersion = tls.VersionTLS12 // enable TLS_FALLBACK_SCSV: https://go-review.googlesource.com/#/c/1776/

	// Use all available ciphersuites minus RC4 and 3DES in a sane order.
	// This configuration has forward secrecy for supported browsers, and gets
	// an ‘A’ grade on SSL Labs.
	c.CipherSuites = []uint16{
		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
	}
	c.PreferServerCipherSuites = true

	return c
}
Beispiel #3
0
// SecureTLSConfig enforces the default minimum security settings for the
// cluster.
// TODO: allow override
func SecureTLSConfig(config *tls.Config) *tls.Config {
	// Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS
	// Can't use SSLv3 because of POODLE and BEAST
	// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
	// Can't use TLSv1.1 because of RC4 cipher usage
	config.MinVersion = tls.VersionTLS12
	// In a legacy environment, allow cipher control to be disabled.
	if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 {
		config.PreferServerCipherSuites = true
		config.CipherSuites = []uint16{
			// Ciphers below are selected and ordered based on the recommended "Intermediate compatibility" suite
			// Compare with available ciphers when bumping Go versions
			//
			// Available ciphers from last comparison (go 1.6):
			// TLS_RSA_WITH_RC4_128_SHA - no
			// TLS_RSA_WITH_3DES_EDE_CBC_SHA
			// TLS_RSA_WITH_AES_128_CBC_SHA
			// TLS_RSA_WITH_AES_256_CBC_SHA
			// TLS_RSA_WITH_AES_128_GCM_SHA256
			// TLS_RSA_WITH_AES_256_GCM_SHA384
			// TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - no
			// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
			// TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
			// TLS_ECDHE_RSA_WITH_RC4_128_SHA - no
			// TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
			// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
			// TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
			// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
			// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
			// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
			// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			// the next two are in the intermediate suite, but go1.6 http2 complains when they are included at the recommended index
			// fixed in https://github.com/golang/go/commit/b5aae1a2845f157a2565b856fb2d7773a0f7af25 in go1.7
			// tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
			// tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
			tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
		}
	} else {
		glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set")
	}
	return config
}
Beispiel #4
0
// ListenAndServeTLSWithSNI serves TLS with Server Name Indication (SNI) support, which allows
// multiple sites (different hostnames) to be served from the same address. This method is
// adapted directly from the std lib's net/http ListenAndServeTLS function, which was
// written by the Go Authors. It has been modified to support multiple certificate/key pairs.
func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error {
	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	config := new(tls.Config)
	if srv.TLSConfig != nil {
		*config = *srv.TLSConfig
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"http/1.1"}
	}

	// Here we diverge from the stdlib a bit by loading multiple certs/key pairs
	// then we map the server names to their certs
	var err error
	config.Certificates = make([]tls.Certificate, len(tlsConfigs))
	for i, tlsConfig := range tlsConfigs {
		config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key)
		if err != nil {
			return err
		}
	}
	config.BuildNameToCertificate()

	// Customize our TLS configuration
	config.MinVersion = tlsConfigs[0].ProtocolMinVersion
	config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion
	config.CipherSuites = tlsConfigs[0].Ciphers
	config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites

	// TLS client authentication, if user enabled it
	err = setupClientAuth(tlsConfigs, config)
	if err != nil {
		return err
	}

	// Create listener and we're on our way
	conn, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	tlsListener := tls.NewListener(conn, config)

	return srv.Serve(tlsListener)
}
Beispiel #5
0
func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error {
	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	config := new(tls.Config)
	if srv.TLSConfig != nil {
		*config = *srv.TLSConfig
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"http/1.1"}
	}

	var err error
	config.Certificates = make([]tls.Certificate, len(tlsConfigs))
	for i, tlsConfig := range tlsConfigs {
		config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key)
		if err != nil {
			return err
		}
	}
	config.BuildNameToCertificate()

	config.MinVersion = tlsConfigs[0].ProtocolMinVersion
	config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion
	config.CipherSuites = tlsConfigs[0].Ciphers
	config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites

	err = setupClientAuth(tlsConfigs, config)
	if err != nil {
		return err
	}

	conn, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	tlsListener := tls.NewListener(conn, config)

	return srv.Serve(tlsListener)
}
Beispiel #6
0
// SecureTLSConfig enforces the default minimum security settings for the
// cluster.
// TODO: allow override
func SecureTLSConfig(config *tls.Config) *tls.Config {
	// Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS
	// Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability)
	config.MinVersion = tls.VersionTLS10
	// In a legacy environment, allow cipher control to be disabled.
	if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 {
		config.PreferServerCipherSuites = true
		config.CipherSuites = []uint16{
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
			tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
		}
	} else {
		glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set")
	}
	return config
}
Beispiel #7
0
func loadTLS(keyPath, certPath string) (*tls.Config, error) {
	tlsConfig := new(tls.Config)

	tlsConfig.PreferServerCipherSuites = true
	tlsConfig.CipherSuites = []uint16{
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}

	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		logging.Error("config", "Error loading tls certificate and key files.")
		logging.Error("config", err.Error())
		return nil, err
	}

	tlsConfig.Certificates = []tls.Certificate{cert}
	tlsConfig.BuildNameToCertificate()

	return tlsConfig, nil
}
Beispiel #8
0
// MakeTLSConfig reduces configs into a single tls.Config.
// If TLS is to be disabled, a nil tls.Config will be returned.
func MakeTLSConfig(configs []*Config) (*tls.Config, error) {
	if configs == nil || len(configs) == 0 {
		return nil, nil
	}

	config := new(tls.Config)
	ciphersAdded := make(map[uint16]struct{})
	configMap := make(configGroup)

	for i, cfg := range configs {
		if cfg == nil {
			// avoid nil pointer dereference below
			configs[i] = new(Config)
			continue
		}

		// Key this config by its hostname; this
		// overwrites configs with the same hostname
		configMap[cfg.Hostname] = cfg

		// Can't serve TLS and not-TLS on same port
		if i > 0 && cfg.Enabled != configs[i-1].Enabled {
			thisConfProto, lastConfProto := "not TLS", "not TLS"
			if cfg.Enabled {
				thisConfProto = "TLS"
			}
			if configs[i-1].Enabled {
				lastConfProto = "TLS"
			}
			return nil, fmt.Errorf("cannot multiplex %s (%s) and %s (%s) on same listener",
				configs[i-1].Hostname, lastConfProto, cfg.Hostname, thisConfProto)
		}

		// Union cipher suites
		for _, ciph := range cfg.Ciphers {
			if _, ok := ciphersAdded[ciph]; !ok {
				ciphersAdded[ciph] = struct{}{}
				config.CipherSuites = append(config.CipherSuites, ciph)
			}
		}

		// Can't resolve conflicting PreferServerCipherSuites settings
		if i > 0 && cfg.PreferServerCipherSuites != configs[i-1].PreferServerCipherSuites {
			return nil, fmt.Errorf("cannot both use PreferServerCipherSuites and not use it")
		}
		config.PreferServerCipherSuites = cfg.PreferServerCipherSuites

		// Go with the widest range of protocol versions
		if config.MinVersion == 0 || cfg.ProtocolMinVersion < config.MinVersion {
			config.MinVersion = cfg.ProtocolMinVersion
		}
		if cfg.ProtocolMaxVersion > config.MaxVersion {
			config.MaxVersion = cfg.ProtocolMaxVersion
		}

		// Go with the strictest ClientAuth type
		if cfg.ClientAuth > config.ClientAuth {
			config.ClientAuth = cfg.ClientAuth
		}
	}

	// Is TLS disabled? If so, we're done here.
	// By now, we know that all configs agree
	// whether it is or not, so we can just look
	// at the first one.
	if len(configs) == 0 || !configs[0].Enabled {
		return nil, nil
	}

	// Default cipher suites
	if len(config.CipherSuites) == 0 {
		config.CipherSuites = defaultCiphers
	}

	// For security, ensure TLS_FALLBACK_SCSV is always included
	if config.CipherSuites[0] != tls.TLS_FALLBACK_SCSV {
		config.CipherSuites = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.CipherSuites...)
	}

	// Set up client authentication if enabled
	if config.ClientAuth != tls.NoClientCert {
		pool := x509.NewCertPool()
		clientCertsAdded := make(map[string]struct{})
		for _, cfg := range configs {
			for _, caFile := range cfg.ClientCerts {
				// don't add cert to pool more than once
				if _, ok := clientCertsAdded[caFile]; ok {
					continue
				}
				clientCertsAdded[caFile] = struct{}{}

				// Any client with a certificate from this CA will be allowed to connect
				caCrt, err := ioutil.ReadFile(caFile)
				if err != nil {
					return nil, err
				}

				if !pool.AppendCertsFromPEM(caCrt) {
					return nil, fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile)
				}
			}
		}
		config.ClientCAs = pool
	}

	// Associate the GetCertificate callback, or almost nothing we just did will work
	config.GetCertificate = configMap.GetCertificate

	return config, nil
}
Beispiel #9
0
func main() {
	http.HandleFunc("/", newLoggingHandleFunc(rootHandler))
	http.HandleFunc("/new", newLoggingHandleFunc(newHandler))
	http.HandleFunc("/view/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(viewHandler))))
	http.HandleFunc("/edit/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(editHandler))))
	http.HandleFunc("/save/", newLoggingHandleFunc(titleHandler(saveHandler)))
	http.HandleFunc("/del/", newLoggingHandleFunc(titleHandler(delHandler)))
	http.HandleFunc("/front", newLoggingHandleFunc(newGzipHandleFunc(frontHandler)))
	http.HandleFunc("/hsts_hpkp", hsts_hpkp)
	log.SetPrefix("goWiki: ")
	log.Println("listening... on port", HTTPS_PORT)
	go func() {
		for {
			err := func() error {
				var OCSPC OCSPCert
				var err error
				cert, err := tls.LoadX509KeyPair(CERT, KEY)
				if err != nil {
					return err
				}
				OCSPC.cert = &cert
				if OCSPC.cert.Leaf, err = x509.ParseCertificate(OCSPC.cert.Certificate[0]); err != nil {
					return err
				}
				issuerRAW, err := ioutil.ReadFile(ISSUER)
				if err != nil {
					return err
				}
				for {
					var issuerPEM *pem.Block
					issuerPEM, issuerRAW = pem.Decode(issuerRAW)
					if issuerPEM == nil {
						break
					}
					if issuerPEM.Type == "CERTIFICATE" {
						OCSPC.issuer, err = x509.ParseCertificate(issuerPEM.Bytes)
						if err != nil {
							return err
						}
					}
				}
				if OCSPC.issuer == nil {
					return errors.New("no issuer")
				}
				OCSPC.req, err = ocsp.CreateRequest(OCSPC.cert.Leaf, OCSPC.issuer, nil)
				if err != nil {
					return err
				}
				err = OCSPC.updateStaple()
				if err != nil {
					return err
				}
				go OCSPC.stapleLoop()
				TLSConfig := new(tls.Config)
				TLSConfig.Certificates = []tls.Certificate{cert}
				TLSConfig.CipherSuites = []uint16{
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
					tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
					tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_RSA_WITH_AES_128_CBC_SHA,
					tls.TLS_RSA_WITH_AES_256_CBC_SHA,
					tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
					tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}
				TLSConfig.PreferServerCipherSuites = true
				TLSConfig.MinVersion = tls.VersionTLS11
				//MaxVersion needed because of bug with TLS_FALLBACK_SCSV gonna be fixed in go 1.5
				TLSConfig.MaxVersion = tls.VersionTLS12
				TLSConfig.NextProtos = []string{"http/1.1"}
				TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
					OCSPC.RLock()
					defer OCSPC.RUnlock()
					return OCSPC.cert, nil
				}
				ln, err := net.Listen("tcp", HTTPS_PORT)
				if err != nil {
					return err
				}
				tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, TLSConfig)
				return new(http.Server).Serve(tlsListener)
			}()
			if err != nil {
				log.Println(err)
			}
			time.Sleep(time.Second * TIMEOUT)
		}
	}()
	for {
		log.Println("redirecting from port", HTTP_PORT, "to", HTTPS_PORT)
		err := http.ListenAndServe(HTTP_PORT, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("X-Frame-Options", "SAMEORIGIN")
			w.Header().Set("Server", "Jesus")
			log.Println("redirecting http", r.RemoteAddr, "to https", DOMAIN+HTTPS_PORT+r.URL.Path)
			http.Redirect(w, r, "https://"+DOMAIN+HTTPS_PORT+r.URL.Path, http.StatusMovedPermanently)
		}))
		if err != nil {
			log.Println(err)
		}
		time.Sleep(time.Second * TIMEOUT)
	}
}
Beispiel #10
0
func main() {

	flag.Parse()

	log.Printf("Rosella v%s Initialising.", VERSION)

	//Init rosella itself
	server := NewServer()
	server.name = *serverName

	if *authFile != "" {
		log.Printf("Loading auth file: %q", *authFile)

		f, err := os.Open(*authFile)
		if err != nil {
			log.Fatal(err)
		}
		data := make([]byte, 1024)
		size, err := f.Read(data)
		if err != nil {
			log.Fatal(err)
		}

		lines := strings.Split(string(data[:size]), "\n")
		for _, line := range lines {
			if strings.HasPrefix(line, "#") {
				continue
			}
			fields := strings.Fields(line)

			if len(fields) == 2 {
				server.operatorMap[fields[0]] = fields[1]
			}
		}
	}

	if *motdFile != "" {
		log.Printf("Loading motd file: %q", *motdFile)

		f, err := os.Open(*motdFile)
		if err != nil {
			log.Fatal(err)
		}
		data := make([]byte, 1024)
		size, err := f.Read(data)
		if err != nil {
			log.Fatal(err)
		}

		server.motd = string(data[:size])
	}

	go server.Run()

	tlsConfig := new(tls.Config)

	tlsConfig.PreferServerCipherSuites = true
	tlsConfig.CipherSuites = []uint16{
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}

	cert, err := tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile)
	if err != nil {
		log.Printf("Error loading tls certificate and key files.")
		log.Printf(err.Error())
		return
	}

	log.Printf("Loaded certificate and key successfully.")

	tlsConfig.Certificates = []tls.Certificate{cert}

	//Fills out tlsConfig.NameToCertificate
	tlsConfig.BuildNameToCertificate()

	tlsListener, err := tls.Listen("tcp", *ircAddress, tlsConfig)
	if err != nil {
		log.Printf("Could not open tls listener.")
		log.Printf(err.Error())
		return
	}

	log.Printf("Listening on %s", *ircAddress)

	if syscall.Getuid() == 0 {
		if *groupId < 1 || *userId < 1 {
			log.Printf("Rosella may not be run as root. Please specify a non-root uid and gid that it may drop to.")
			return
		}
		if syscall.Setgid(*groupId) != nil {
			log.Printf("Failed to set gid to %i", *groupId)
			return
		}
		if syscall.Setuid(*userId) != nil {
			log.Printf("Failed to set uid to %i", *userId)
			return
		}
	}

	for {
		conn, err := tlsListener.Accept()
		if err != nil {
			log.Printf("Error accepting connection.")
			log.Printf(err.Error())
			continue
		}

		server.HandleConnection(conn)
	}
}