Skip to content

Instantly share code, notes, and snippets.

@cardonator
Created August 29, 2018 03:56
Show Gist options
  • Save cardonator/6a2c38614fafe2d7616d93ebdc65979e to your computer and use it in GitHub Desktop.
Save cardonator/6a2c38614fafe2d7616d93ebdc65979e to your computer and use it in GitHub Desktop.
package main
import (
"encoding/csv"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"strings"
"sync"
"time"
)
type crtsh struct {
MinCertID int `json:"min_cert_id"`
}
var noCertDomains []string
var links []string
func main() {
file, err := os.Open("search-domains.csv")
if err != nil {
log.Fatal("Couldn't open the file to parse")
}
domainNames := csv.NewReader(file)
t := &http.Transport{
MaxIdleConns: 100,
IdleConnTimeout: 1,
DisableKeepAlives: true,
}
client := &http.Client{
Timeout: time.Second * 2,
Transport: t,
}
count := 0
c := make(chan string, 100)
var wg sync.WaitGroup
go func(client *http.Client, wg *sync.WaitGroup) {
for domainName := range c {
count = count + 1
/*if count%20 == 0 {
println("open files:", countOpenFiles())
}*/
println("Processing", count, domainName, len(c))
go queryCrtsh(domainName, wg, client)
}
}(client, &wg)
countAdd := 0
for {
domainName, err := domainNames.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
countAdd = countAdd + 1
if countAdd%100 == 0 {
println(countAdd, "-- Adding to the channel:", domainName[0])
}
wg.Add(1)
c <- domainName[0]
}
close(c)
wg.Wait()
fmt.Print(strings.Join(links[:], "\n"))
println("Found %d links", len(links))
println("Unfound domains %d", len(noCertDomains))
}
func queryCrtsh(domainName string, wg *sync.WaitGroup, client *http.Client) {
defer wg.Done()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://crt.sh/?q=%s&output=json", domainName), nil)
if err != nil {
println(domainName)
log.Println(fmt.Sprintf("Failed to create request"))
log.Fatal(err)
}
req.Close = true
req.Header.Set("User-Agent", "Certopia")
req.Header.Set("Connection", "close")
res, err := client.Do(req)
if err != nil {
println(domainName)
log.Println("Failed to get response", domainName, countOpenFiles())
log.Fatal(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
println(domainName)
log.Println(fmt.Sprintf("Failed to read response"))
log.Fatal(err)
}
formatBody := fmt.Sprintf("[%s]", strings.Replace(string(body[:]), "}{", "},{", -1))
var certs []crtsh
err = json.Unmarshal([]byte(formatBody), &certs)
if err != nil {
println(domainName)
log.Println(fmt.Sprintf("Failed to unmarshal body %s", formatBody))
log.Fatal(err)
}
if len(certs) == 0 {
noCertDomains = append(noCertDomains, domainName)
}
// for loop gets a list of certs, so pre and leaf
for i := range certs {
links = append(links, fmt.Sprintf("https://crt.sh/?id=%d", certs[i].MinCertID))
}
}
func countOpenFiles() int {
out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -p %v", os.Getpid())).Output()
if err != nil {
log.Fatal(err)
}
lines := strings.Split(string(out), "\n")
return len(lines) - 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment