github.com/edermi/gophish_mods@v0.7.0/util/util.go (about) 1 package util 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/csv" 10 "encoding/pem" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "math/big" 15 "net/http" 16 "net/mail" 17 "os" 18 "regexp" 19 "time" 20 21 log "github.com/gophish/gophish/logger" 22 "github.com/gophish/gophish/models" 23 "github.com/jordan-wright/email" 24 ) 25 26 var ( 27 firstNameRegex = regexp.MustCompile(`(?i)first[\s_-]*name`) 28 lastNameRegex = regexp.MustCompile(`(?i)last[\s_-]*name`) 29 emailRegex = regexp.MustCompile(`(?i)email`) 30 positionRegex = regexp.MustCompile(`(?i)position`) 31 ) 32 33 // ParseMail takes in an HTTP Request and returns an Email object 34 // TODO: This function will likely be changed to take in a []byte 35 func ParseMail(r *http.Request) (email.Email, error) { 36 e := email.Email{} 37 m, err := mail.ReadMessage(r.Body) 38 if err != nil { 39 fmt.Println(err) 40 } 41 body, err := ioutil.ReadAll(m.Body) 42 e.HTML = body 43 return e, err 44 } 45 46 // ParseCSV contains the logic to parse the user provided csv file containing Target entries 47 func ParseCSV(r *http.Request) ([]models.Target, error) { 48 mr, err := r.MultipartReader() 49 ts := []models.Target{} 50 if err != nil { 51 return ts, err 52 } 53 for { 54 part, err := mr.NextPart() 55 if err == io.EOF { 56 break 57 } 58 // Skip the "submit" part 59 if part.FileName() == "" { 60 continue 61 } 62 defer part.Close() 63 reader := csv.NewReader(part) 64 reader.TrimLeadingSpace = true 65 record, err := reader.Read() 66 if err == io.EOF { 67 break 68 } 69 fi := -1 70 li := -1 71 ei := -1 72 pi := -1 73 fn := "" 74 ln := "" 75 ea := "" 76 ps := "" 77 for i, v := range record { 78 switch { 79 case firstNameRegex.MatchString(v): 80 fi = i 81 case lastNameRegex.MatchString(v): 82 li = i 83 case emailRegex.MatchString(v): 84 ei = i 85 case positionRegex.MatchString(v): 86 pi = i 87 } 88 } 89 for { 90 record, err := reader.Read() 91 if err == io.EOF { 92 break 93 } 94 if fi != -1 && len(record) > fi { 95 fn = record[fi] 96 } 97 if li != -1 && len(record) > li { 98 ln = record[li] 99 } 100 if ei != -1 && len(record) > ei { 101 csvEmail, err := mail.ParseAddress(record[ei]) 102 if err != nil { 103 continue 104 } 105 ea = csvEmail.Address 106 } 107 if pi != -1 && len(record) > pi { 108 ps = record[pi] 109 } 110 t := models.Target{ 111 BaseRecipient: models.BaseRecipient{ 112 FirstName: fn, 113 LastName: ln, 114 Email: ea, 115 Position: ps, 116 }, 117 } 118 ts = append(ts, t) 119 } 120 } 121 return ts, nil 122 } 123 124 // CheckAndCreateSSL is a helper to setup self-signed certificates for the administrative interface. 125 func CheckAndCreateSSL(cp string, kp string) error { 126 // Check whether there is an existing SSL certificate and/or key, and if so, abort execution of this function 127 if _, err := os.Stat(cp); !os.IsNotExist(err) { 128 return nil 129 } 130 if _, err := os.Stat(kp); !os.IsNotExist(err) { 131 return nil 132 } 133 134 log.Infof("Creating new self-signed certificates for administration interface") 135 136 priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 137 138 notBefore := time.Now() 139 // Generate a certificate that lasts for 10 years 140 notAfter := notBefore.Add(10 * 365 * 24 * time.Hour) 141 142 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 143 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 144 145 if err != nil { 146 return fmt.Errorf("TLS Certificate Generation: Failed to generate a random serial number: %s", err) 147 } 148 149 template := x509.Certificate{ 150 SerialNumber: serialNumber, 151 Subject: pkix.Name{ 152 Organization: []string{"Gophish"}, 153 }, 154 NotBefore: notBefore, 155 NotAfter: notAfter, 156 157 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 158 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 159 BasicConstraintsValid: true, 160 } 161 162 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv) 163 if err != nil { 164 return fmt.Errorf("TLS Certificate Generation: Failed to create certificate: %s", err) 165 } 166 167 certOut, err := os.Create(cp) 168 if err != nil { 169 return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err) 170 } 171 pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 172 certOut.Close() 173 174 keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 175 if err != nil { 176 return fmt.Errorf("TLS Certificate Generation: Failed to open %s for writing", kp) 177 } 178 179 b, err := x509.MarshalECPrivateKey(priv) 180 if err != nil { 181 return fmt.Errorf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err) 182 } 183 184 pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) 185 keyOut.Close() 186 187 log.Info("TLS Certificate Generation complete") 188 return nil 189 }