clientHelloServerName returns the SNI server name inside the TLS ClientHello, without consuming any bytes from br. On any error, the empty string is returned.
(br *bufio.Reader)
| 36 | // without consuming any bytes from br. |
| 37 | // On any error, the empty string is returned. |
| 38 | func clientHelloServerName(br *bufio.Reader) (sni string) { |
| 39 | const recordHeaderLen = 5 |
| 40 | hdr, err := br.Peek(recordHeaderLen) |
| 41 | if err != nil { |
| 42 | return "" |
| 43 | } |
| 44 | const recordTypeHandshake = 0x16 |
| 45 | if hdr[0] != recordTypeHandshake { |
| 46 | return "" // Not TLS. |
| 47 | } |
| 48 | recLen := int(hdr[3])<<8 | int(hdr[4]) // ignoring version in hdr[1:3] |
| 49 | helloBytes, err := br.Peek(recordHeaderLen + recLen) |
| 50 | if err != nil { |
| 51 | return "" |
| 52 | } |
| 53 | tls.Server(sniSniffConn{r: bytes.NewReader(helloBytes)}, &tls.Config{ |
| 54 | GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) { |
| 55 | sni = hello.ServerName |
| 56 | return nil, nil |
| 57 | }, |
| 58 | }).Handshake() |
| 59 | return |
| 60 | } |
| 61 | |
| 62 | // sniSniffConn is a net.Conn that reads from r, fails on Writes, |
| 63 | // and crashes otherwise. |