func (si *SSLInterceptor) GetHostKeyPair(cn string) (*tls.Certificate, error) { si.mu.Lock() defer si.mu.Unlock() keypair, found := si.keyPairCache[cn] if found { return keypair, nil } keypair, err := cert.GetOrGenerateKeyPair(path.Join(si.HostCertFolder, cn+"_cert.pem"), path.Join(si.HostCertFolder, cn+"_key.pem"), cn, []string{"Sniffy"}, false, si.caParentCert) if err == nil { si.keyPairCache[cn] = keypair } return keypair, err }
func NewSSLInterceptor(handler InterceptHandler, caCertFile, caKeyFile string) (*SSLInterceptor, error) { si := SSLInterceptor{ Handler: handler, GenerateHostCerts: true, // TODO: TEMP HostCertFolder: "cert/interceptor", // TODO: TEMP keyPairCache: map[string]*tls.Certificate{}, mu: &sync.Mutex{}, } _, err := cert.GetOrGenerateKeyPair(caCertFile, caKeyFile, "interceptor.sniffy.local", []string{"Sniffy"}, true, nil) if err != nil { return nil, fmt.Errorf("Couldn't get or generate interceptor CA key pair: %s", err) } caKeyPair, err := tls.LoadX509KeyPair(caCertFile, caKeyFile) if err != nil { return nil, fmt.Errorf("Couldn't load interceptor CA key pair: %s", err) } si.caKeyPair = &caKeyPair si.caParentCert, err = x509.ParseCertificate(caKeyPair.Certificate[0]) if err != nil { return nil, fmt.Errorf("Couldn't parse interceptor CA key pair: %s", err) } return &si, nil }
func boot() { var err error initLogger(logBoot) config, err = loadConfig() if err != nil { setup() return } err = connectDB() if err != nil { log.Fatal("Couldn't open database:", err) } err = initDB() if err != nil { log.Fatalln("Failed to initialize database:", err, "\r\nIf the database settings have changed, please delete "+configFile+", then re-run\r\nSniffy to define new database connection settings. (Existing information in\r\nthe database, if it exists, will not be removed.)") } err = loadSettings() if err != nil { log.Fatalln("Failed to load settings from database:", err) } debug.Println("Settings loaded") os.Mkdir(config.certFolder, 0755) _, err = cert.GetOrGenerateKeyPair(config.webCertFile, config.webKeyFile, "web.sniffy.local", []string{"Sniffy"}, false, nil) if err != nil { log.Fatalln("Couldn't generate web interface RSA key pair:", err) } loadTemplates() pss, err := getProxyServers("") if err != nil { log.Println("Error starting proxy servers:", err) } else { for _, v := range pss { proxyServers = append(proxyServers, v) go func(ps *proxyServer) { var err error if ps.CertFile != "" && ps.KeyFile != "" { err = ps.ps.ListenAndServeTLS(v.CertFile, v.KeyFile) } else { err = ps.ps.ListenAndServe() } if err != nil { log.Println("Proxy server", ps.Name, "stopped:", err) } }(v) } } dss, err := getDummyServers("") if err != nil { log.Println("Error starting dummy servers:", err) } else { for _, v := range dss { dummyServers = append(dummyServers, v) if v.CertFile != "" && v.KeyFile != "" { _, err = cert.GetOrGenerateKeyPair(v.CertFile, v.KeyFile, "dummy.sniffy.local", []string{"Sniffy"}, false, nil) } go v.ds.Run() } } os.Mkdir(config.interceptorCertFolder, 0755) sslInterceptor, err = sniff.NewSSLInterceptor(proxyServers[0], config.interceptorCACertFile, config.interceptorCAKeyFile) if err != nil { log.Fatalln("Couldn't create SSL interceptor:", err) } if config.preloadInterceptorCerts { rows, err := db.Query("SELECT cn FROM certs") if err == nil { for rows.Next() { var cn string rows.Scan(&cn) if cn != "web.sniffy.local" && cn != "interceptor.sniffy.local" { go func() { _, err := sslInterceptor.GetHostKeyPair(cn) if err != nil { log.Println("Couldn't preload RSA key pair for", cn+":", err) } }() } } } } // BEGIN TESTING! test := false if test { http.HandleFunc("/", testfunc) testkp, _ := sslInterceptor.GetHostKeyPair("sheeped.com") // testkp.Certificate = append(testkp.Certificate, si.caKeyPair.Certificate...) config := &tls.Config{ Rand: rand.Reader, NextProtos: []string{"http/1.1"}, Certificates: []tls.Certificate{ *testkp, // si.caKeyPair, }, } log.Println("LAUNCHING TEST SSL SERVER :20010") l, _ := tls.Listen("tcp", ":20010", config) srv := http.Server{} srv.Serve(l) // END TESTING! } wsHost, err := getSetting("WebServerHost") if err != nil { wsHost = "127.0.0.1" } wsPort, err := getIntSetting("WebServerPort") if err != nil || wsPort < 1 || wsPort > 65535 { wsPort = defaultWebServerPort } // log.Println("Logging to", logFile) initLogger(logToFile) fmt.Println("") fmt.Printf("Sniffy interface running on https://%s:%d\n", wsHost, wsPort) ws := NewWebServer(wsHost, uint16(wsPort)) go ws.Run() fmt.Println("") fmt.Print("For recovery, enter administrator password: ") prompt(stateLogin) }