Select Git revision
-
Janne Mareike Koschinski authoredJanne Mareike Koschinski authored
main.go 2.85 KiB
package main
import (
"bufio"
"crypto/tls"
"encoding/binary"
"flag"
"fmt"
"net"
)
const ProtocolMagic uint32 = 0x42b33f00
const ProtocolFeatureTls uint8 = 0x01
const ProtocolFeatureCompression uint8 = 0x02
const ProtocolDatastream uint32 = 0x02
type connection struct {
hostname string
socket net.Conn
tlsSocket *tls.Conn
readWriter *bufio.ReadWriter
buffer []byte
}
func makeConnection(address string, port int) connection {
socket, err := net.Dial("tcp", fmt.Sprintf("%s:%d", address, port))
if err != nil {
panic(err.Error())
}
return connection{
hostname: address,
socket: socket,
readWriter: bufio.NewReadWriter(
bufio.NewReader(socket),
bufio.NewWriter(socket),
),
buffer: make([]byte, 4),
}
}
func (c *connection) write(data uint32) {
binary.BigEndian.PutUint32(c.buffer, data)
_, err := c.readWriter.Write(c.buffer)
if err != nil {
panic(err.Error())
}
}
func (c *connection) read(len int) []byte {
buffer := make([]byte, len)
_, err := c.readWriter.Read(buffer)
if err != nil {
panic(err.Error())
}
return buffer
}
func (c *connection) flush() {
err := c.readWriter.Flush()
if err != nil {
panic(err.Error())
}
}
func (c *connection) withTLS(verify bool) {
config := &tls.Config{
ServerName: c.hostname,
InsecureSkipVerify: !verify,
}
c.tlsSocket = tls.Client(c.socket, config)
c.readWriter = bufio.NewReadWriter(
bufio.NewReader(c.tlsSocket),
bufio.NewWriter(c.tlsSocket),
)
err := c.tlsSocket.Handshake()
if err != nil {
panic(err.Error())
}
}
func (c *connection) tlsState() *tls.ConnectionState {
if c.tlsSocket != nil {
state := c.tlsSocket.ConnectionState()
return &state
} else {
return nil
}
}
func (c *connection) close() {
_ = c.readWriter.Flush()
_ = c.tlsSocket.Close()
_ = c.socket.Close()
}
type protocolInfo struct {
flagTLS bool
flagCompression bool
data uint16
version uint8
}
func parseProtocolInfo(data []byte) protocolInfo {
rawFeatures := data[0]
rawData := data[1:3]
rawVersion := data[3]
return protocolInfo{
rawFeatures&ProtocolFeatureTls != 0,
rawFeatures&ProtocolFeatureCompression != 0,
binary.BigEndian.Uint16(rawData),
rawVersion,
}
}
func main() {
hostname := flag.String("hostname", "", "address of server to connect to")
port := flag.Int("port", 4242, "port of server to connect to")
flag.Parse()
conn := makeConnection(*hostname, *port)
conn.write(ProtocolMagic | uint32(ProtocolFeatureTls))
supportedProtocols := []uint32{
ProtocolDatastream,
}
for _, protocol := range supportedProtocols {
conn.write(protocol)
}
conn.write(1 << 31)
conn.flush()
protocolInfo := parseProtocolInfo(conn.read(4))
if protocolInfo.flagTLS {
conn.withTLS(false)
}
if state := conn.tlsState(); state != nil {
for _, cert := range state.PeerCertificates {
println(cert.NotAfter.String())
}
}
conn.close()
}