@ -25,6 +25,7 @@ import (
"time"
"time"
humanize "github.com/dustin/go-humanize"
humanize "github.com/dustin/go-humanize"
"github.com/minio/minio-go/pkg/set"
)
)
const (
const (
@ -64,16 +65,19 @@ type Server struct {
// Start - start HTTP server
// Start - start HTTP server
func ( srv * Server ) Start ( ) ( err error ) {
func ( srv * Server ) Start ( ) ( err error ) {
// Take a copy of server fields.
// Take a copy of server fields.
tlsConfig := srv . TLSConfig
var tlsConfig * tls . Config
if srv . TLSConfig != nil {
tlsConfig = srv . TLSConfig . Clone ( )
}
readTimeout := srv . ReadTimeout
readTimeout := srv . ReadTimeout
writeTimeout := srv . WriteTimeout
writeTimeout := srv . WriteTimeout
handler := srv . Handler
handler := srv . Handler // if srv.Handler holds non-synced state -> possible data race
addrs := srv . Addrs
addrs := set . CreateStringSet ( s rv . Addrs ... ) . ToSlice ( ) // copy and remove duplicates
tcpKeepAliveTimeout := srv . TCPKeepAliveTimeout
tcpKeepAliveTimeout := srv . TCPKeepAliveTimeout
updateBytesReadFunc := srv . UpdateBytesReadFunc
updateBytesReadFunc := srv . UpdateBytesReadFunc
updateBytesWrittenFunc := srv . UpdateBytesWrittenFunc
updateBytesWrittenFunc := srv . UpdateBytesWrittenFunc
errorLogFunc := srv . ErrorLogFunc
errorLogFunc := srv . ErrorLogFunc // if srv.ErrorLogFunc holds non-synced state -> possible data race
// Create new HTTP listener.
// Create new HTTP listener.
var listener * httpListener
var listener * httpListener
@ -118,9 +122,12 @@ func (srv *Server) Start() (err error) {
// Shutdown - shuts down HTTP server.
// Shutdown - shuts down HTTP server.
func ( srv * Server ) Shutdown ( ) error {
func ( srv * Server ) Shutdown ( ) error {
srv . listenerMutex . Lock ( )
if srv . listener == nil {
if srv . listener == nil {
srv . listenerMutex . Unlock ( )
return errors . New ( "server not initialized" )
return errors . New ( "server not initialized" )
}
}
srv . listenerMutex . Unlock ( )
if atomic . AddUint32 ( & srv . inShutdown , 1 ) > 1 {
if atomic . AddUint32 ( & srv . inShutdown , 1 ) > 1 {
// shutdown in progress
// shutdown in progress
@ -149,12 +156,32 @@ func (srv *Server) Shutdown() error {
}
}
}
}
// Secure Go implementations of modern TLS ciphers
// The following ciphers are excluded because:
// - RC4 ciphers: RC4 is broken
// - 3DES ciphers: Because of the 64 bit blocksize of DES (Sweet32)
// - CBC-SHA256 ciphers: No countermeasures against Lucky13 timing attack
// - CBC-SHA ciphers: Legacy ciphers (SHA-1) and non-constant time
// implementation of CBC.
// (CBC-SHA ciphers can be enabled again if required)
// - RSA key exchange ciphers: Disabled because of dangerous PKCS1-v1.5 RSA
// padding scheme. See Bleichenbacher attacks.
var defaultCipherSuites = [ ] uint16 {
tls . TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 ,
tls . TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 ,
tls . TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
tls . TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
tls . TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,
tls . TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
}
// NewServer - creates new HTTP server using given arguments.
// NewServer - creates new HTTP server using given arguments.
func NewServer ( addrs [ ] string , handler http . Handler , certificate * tls . Certificate ) * Server {
func NewServer ( addrs [ ] string , handler http . Handler , certificate * tls . Certificate ) * Server {
var tlsConfig * tls . Config
var tlsConfig * tls . Config
if certificate != nil {
if certificate != nil {
tlsConfig = & tls . Config {
tlsConfig = & tls . Config {
PreferServerCipherSuites : true ,
PreferServerCipherSuites : true ,
CipherSuites : defaultCipherSuites ,
MinVersion : tls . VersionTLS12 ,
MinVersion : tls . VersionTLS12 ,
NextProtos : [ ] string { "http/1.1" , "h2" } ,
NextProtos : [ ] string { "http/1.1" , "h2" } ,
}
}