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