Merge pull request #1 from joshlf/stealchain-server
Add stealchain-server utility
This commit is contained in:
commit
70d7ff505b
|
@ -0,0 +1,17 @@
|
|||
stealchain-server
|
||||
|
||||
This is a utility to extract the verified X.509 chain from a TLS
|
||||
connection initiated by another client. It listens on a port, and
|
||||
for each connection, it will dump the certificates that the peer
|
||||
actually sent (and not the verified chain that is built from this).
|
||||
|
||||
It was written to assist in debugging issues with certificate chains.
|
||||
|
||||
There are a few knobs:
|
||||
|
||||
-listen specifies the address to listen on.
|
||||
|
||||
-ca allows the trusted CA roots to be specified via a PEM bundle of
|
||||
root certificates.
|
||||
|
||||
-verify requires that the client present a valid certificate chain.
|
|
@ -0,0 +1,83 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/kisom/goutils/die"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg := &tls.Config{}
|
||||
|
||||
var sysRoot, listenAddr string
|
||||
var verify bool
|
||||
flag.StringVar(&sysRoot, "ca", "", "provide an alternate CA bundle")
|
||||
flag.StringVar(&listenAddr, "listen", ":443", "address to listen on")
|
||||
flag.BoolVar(&verify, "verify", false, "verify client certificates")
|
||||
flag.Parse()
|
||||
|
||||
if verify {
|
||||
cfg.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
}
|
||||
if sysRoot != "" {
|
||||
pemList, err := ioutil.ReadFile(sysRoot)
|
||||
die.If(err)
|
||||
|
||||
roots := x509.NewCertPool()
|
||||
if !roots.AppendCertsFromPEM(pemList) {
|
||||
fmt.Printf("[!] no valid roots found")
|
||||
roots = nil
|
||||
}
|
||||
|
||||
cfg.RootCAs = roots
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", listenAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
raddr := conn.RemoteAddr()
|
||||
tconn := tls.Server(conn, cfg)
|
||||
cs := tconn.ConnectionState()
|
||||
if len(cs.PeerCertificates) == 0 {
|
||||
fmt.Printf("[+] %v: no chain presented\n", raddr)
|
||||
continue
|
||||
}
|
||||
|
||||
var chain []byte
|
||||
for _, cert := range cs.PeerCertificates {
|
||||
p := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
chain = append(chain, pem.EncodeToMemory(p)...)
|
||||
}
|
||||
|
||||
var nonce [16]byte
|
||||
_, err = rand.Read(nonce[:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fname := fmt.Sprintf("%v-%v.pem", raddr, hex.EncodeToString(nonce[:]))
|
||||
err = ioutil.WriteFile(fname, chain, 0644)
|
||||
die.If(err)
|
||||
fmt.Printf("%v: [+] wrote %v.\n", raddr, fname)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue