Hi, 

I've a legacy application at hand that has a nginx as TLS offloader in 
front of it. Besides a simple frontend the application offers an API 
including a PKI infrastructure (CSRs are pushed to server, signed CRTs are 
returned). The nginx is configured to optionally request a client 
certificate ("ssl_verify_client optional") from the requesting party 
(browsers, IoT devices, ...). 

This approach is working for most browsers except OS X's Safari. nginx 
offers a list acceptable client certificate CA names but Safari tends to 
ignore this list and prompts the user to chose a certificate (including 
iCloud certificates and stuff). 

Browsers are not necessarily required to provide a client certificate. IoT 
devices are configured to always provide a client certificate. 

Differing from nginx's and Apache's SSL configuration, the TLS 
implementation of golang seems to offer another client authentication 
mechanism: VerifyClientCertIfGiven (see 
https://golang.org/pkg/crypto/tls/#ClientAuthType). So I decided to give 
golang a try (as a potential TLS offloader replacing nginx) and came up 
with the following simple TLS secured HTTP server: 

package main


import (
   "log"
   "net/http"
   "crypto/tls"
   "crypto/x509"
   "encoding/pem"
   "io/ioutil"
   "fmt"
)


func handler(w http.ResponseWriter, req *http.Request) {
   w.Header().Set("Content-Type", "text/plain")
   w.Write([]byte("Test.\n"))
}


func main() {
   http.HandleFunc("/", handler)

   pemByte, _ := ioutil.ReadFile("ssl/ca.pem")
   block, pemByte := pem.Decode(pemByte)

   cert, err := x509.ParseCertificate(block.Bytes)

   if err != nil {
       fmt.Println(err)
   }

   certPool := x509.NewCertPool()
   certPool.AddCert(cert)

   server := &http.Server{
       TLSConfig: &tls.Config{
           ClientAuth: tls.VerifyClientCertIfGiven,
           ClientCAs: certPool,
       },
       Addr: "0.0.0.0:10443",
    }


    server.TLSConfig.BuildNameToCertificate()

    err = server.ListenAndServeTLS("ssl/server.crt", "ssl/server.key")
 
    if err != nil {
        log.Fatal(err)
    }
}

My initial thought when reading the const "VerifyClientCertIfGiven" was 
that a list of acceptable client certificate CA names will NOT be sent to 
the connecting client, but certificates that are provided will be validated 
against the configured ClientCAs. 

I had a look into the server TLS implementation and I'm wondering about the 
conditional statement "if config.ClientAuth > RequestClientCert" around the 
certificate request message (see 
https://github.com/golang/go/blob/release-branch.go1.7/src/crypto/tls/handshake_server.go#L409).
 

I'm new to golang and my knowledge of the TLS spec isn't good either but 
I'm wondering if this conditional would be better changed to 
"c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == 
RequireAndVerifyClientCert || c.config.ClientAuth == RequestClientCert"? 
>From my point of view "VerifyClientCertIfGiven" has no special meaning and 
acts exactly as RequireAndVerifyClientCert. 

Am I missing something?

BR, Sven

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to