cmd/stealchain-server: Initial commit.
This commit is contained in:
		
							parent
							
								
									54dd461733
								
							
						
					
					
						commit
						68e5822176
					
				| 
						 | 
					@ -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