2014-06-22 02:06:16 +00:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
2016-11-19 18:04:10 +00:00
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/elliptic"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/x509"
|
|
|
|
"crypto/x509/pkix"
|
2014-06-22 02:06:16 +00:00
|
|
|
"encoding/csv"
|
2016-11-19 18:04:10 +00:00
|
|
|
"encoding/pem"
|
|
|
|
"errors"
|
2014-06-22 02:06:16 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2015-02-16 03:53:30 +00:00
|
|
|
"io/ioutil"
|
2016-11-19 18:04:10 +00:00
|
|
|
"log"
|
|
|
|
"math/big"
|
2014-06-22 02:06:16 +00:00
|
|
|
"net/http"
|
2015-02-16 03:53:30 +00:00
|
|
|
"net/mail"
|
2016-11-19 18:04:10 +00:00
|
|
|
"os"
|
|
|
|
"time"
|
2017-02-13 22:56:31 +00:00
|
|
|
"strings"
|
2014-06-22 02:06:16 +00:00
|
|
|
|
2016-01-10 17:03:17 +00:00
|
|
|
"github.com/gophish/gophish/models"
|
2016-02-10 04:29:13 +00:00
|
|
|
"github.com/jordan-wright/email"
|
2017-02-13 12:07:08 +00:00
|
|
|
"github.com/nicksnyder/go-i18n/i18n"
|
2014-06-22 02:06:16 +00:00
|
|
|
)
|
|
|
|
|
2016-11-19 18:04:10 +00:00
|
|
|
// Logger is used to send logging messages to stdout.
|
|
|
|
var Logger = log.New(os.Stdout, " ", log.Ldate|log.Ltime|log.Lshortfile)
|
2017-02-13 22:56:31 +00:00
|
|
|
var B i18n.TranslateFunc
|
|
|
|
var Lang = "en-US"
|
2016-11-19 18:04:10 +00:00
|
|
|
|
2017-02-13 12:07:08 +00:00
|
|
|
func T(text string) string{
|
2017-02-13 22:56:31 +00:00
|
|
|
if B == nil {
|
|
|
|
i18n.MustLoadTranslationFile("translations/" + strings.ToLower(Lang) + ".all.json")
|
|
|
|
B, _ = i18n.Tfunc(Lang)
|
|
|
|
}
|
|
|
|
|
|
|
|
return B(text)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ChangeLang(lang string) {
|
|
|
|
Lang = lang
|
|
|
|
B = nil
|
2017-02-13 12:07:08 +00:00
|
|
|
}
|
|
|
|
|
2015-02-16 03:53:30 +00:00
|
|
|
// ParseMail takes in an HTTP Request and returns an Email object
|
|
|
|
// TODO: This function will likely be changed to take in a []byte
|
|
|
|
func ParseMail(r *http.Request) (email.Email, error) {
|
|
|
|
e := email.Email{}
|
|
|
|
m, err := mail.ReadMessage(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
|
|
|
body, err := ioutil.ReadAll(m.Body)
|
|
|
|
e.HTML = body
|
|
|
|
return e, err
|
|
|
|
}
|
|
|
|
|
2015-02-21 17:36:08 +00:00
|
|
|
// ParseCSV contains the logic to parse the user provided csv file containing Target entries
|
2014-06-22 02:06:16 +00:00
|
|
|
func ParseCSV(r *http.Request) ([]models.Target, error) {
|
|
|
|
mr, err := r.MultipartReader()
|
|
|
|
ts := []models.Target{}
|
|
|
|
if err != nil {
|
|
|
|
return ts, err
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
part, err := mr.NextPart()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
// Skip the "submit" part
|
|
|
|
if part.FileName() == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
defer part.Close()
|
|
|
|
reader := csv.NewReader(part)
|
|
|
|
reader.TrimLeadingSpace = true
|
|
|
|
record, err := reader.Read()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
fi := -1
|
|
|
|
li := -1
|
|
|
|
ei := -1
|
2015-02-21 17:36:08 +00:00
|
|
|
pi := -1
|
2014-06-22 02:06:16 +00:00
|
|
|
fn := ""
|
|
|
|
ln := ""
|
|
|
|
ea := ""
|
2015-02-21 17:36:08 +00:00
|
|
|
ps := ""
|
2014-06-22 02:06:16 +00:00
|
|
|
for i, v := range record {
|
|
|
|
switch {
|
|
|
|
case v == "First Name":
|
|
|
|
fi = i
|
|
|
|
case v == "Last Name":
|
|
|
|
li = i
|
|
|
|
case v == "Email":
|
|
|
|
ei = i
|
2015-02-21 17:36:08 +00:00
|
|
|
case v == "Position":
|
|
|
|
pi = i
|
2014-06-22 02:06:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
record, err := reader.Read()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if fi != -1 {
|
|
|
|
fn = record[fi]
|
|
|
|
}
|
|
|
|
if li != -1 {
|
|
|
|
ln = record[li]
|
|
|
|
}
|
|
|
|
if ei != -1 {
|
|
|
|
ea = record[ei]
|
|
|
|
}
|
2015-02-21 17:36:08 +00:00
|
|
|
if pi != -1 {
|
|
|
|
ps = record[pi]
|
|
|
|
}
|
2014-06-22 02:06:16 +00:00
|
|
|
t := models.Target{
|
|
|
|
FirstName: fn,
|
|
|
|
LastName: ln,
|
|
|
|
Email: ea,
|
2015-02-21 17:36:08 +00:00
|
|
|
Position: ps,
|
2014-06-22 02:06:16 +00:00
|
|
|
}
|
|
|
|
ts = append(ts, t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ts, nil
|
|
|
|
}
|
2016-11-19 18:04:10 +00:00
|
|
|
|
|
|
|
// CheckAndCreateSSL is a helper to setup self-signed certificates for the administrative interface.
|
|
|
|
func CheckAndCreateSSL(cp string, kp string) error {
|
|
|
|
// Check whether there is an existing SSL certificate and/or key, and if so, abort execution of this function
|
|
|
|
if _, err := os.Stat(cp); !os.IsNotExist(err) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if _, err := os.Stat(kp); !os.IsNotExist(err) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger.Printf("Creating new self-signed certificates for administration interface...\n")
|
|
|
|
|
|
|
|
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
|
|
|
|
|
|
|
notBefore := time.Now()
|
|
|
|
// Generate a certificate that lasts for 10 years
|
|
|
|
notAfter := notBefore.Add(10 * 365 * 24 * time.Hour)
|
|
|
|
|
|
|
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
|
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to generate a random serial number: %s", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
template := x509.Certificate{
|
|
|
|
SerialNumber: serialNumber,
|
|
|
|
Subject: pkix.Name{
|
|
|
|
Organization: []string{"Gophish"},
|
|
|
|
},
|
|
|
|
NotBefore: notBefore,
|
|
|
|
NotAfter: notAfter,
|
|
|
|
|
|
|
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
|
|
BasicConstraintsValid: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
|
|
|
|
if err != nil {
|
|
|
|
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to create certificate: %s", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
certOut, err := os.Create(cp)
|
|
|
|
if err != nil {
|
|
|
|
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err))
|
|
|
|
}
|
|
|
|
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
|
|
|
certOut.Close()
|
|
|
|
|
|
|
|
keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
|
|
|
if err != nil {
|
|
|
|
return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing", kp))
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := x509.MarshalECPrivateKey(priv)
|
|
|
|
if err != nil {
|
|
|
|
return errors.New(fmt.Sprintf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
|
|
|
|
keyOut.Close()
|
|
|
|
|
|
|
|
Logger.Println("TLS Certificate Generation complete")
|
|
|
|
return nil
|
|
|
|
}
|