github.com/merlinepedra/gopphish-attack@v0.9.0/models/models.go (about)

     1  package models
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"time"
    11  
    12  	"bitbucket.org/liamstask/goose/lib/goose"
    13  
    14  	mysql "github.com/go-sql-driver/mysql"
    15  	"github.com/gophish/gophish/config"
    16  	log "github.com/gophish/gophish/logger"
    17  	"github.com/jinzhu/gorm"
    18  	_ "github.com/mattn/go-sqlite3" // Blank import needed to import sqlite3
    19  )
    20  
    21  var db *gorm.DB
    22  var conf *config.Config
    23  
    24  const MaxDatabaseConnectionAttempts int = 10
    25  
    26  const (
    27  	CampaignInProgress string = "In progress"
    28  	CampaignQueued     string = "Queued"
    29  	CampaignCreated    string = "Created"
    30  	CampaignEmailsSent string = "Emails Sent"
    31  	CampaignComplete   string = "Completed"
    32  	EventSent          string = "Email Sent"
    33  	EventSendingError  string = "Error Sending Email"
    34  	EventOpened        string = "Email Opened"
    35  	EventClicked       string = "Clicked Link"
    36  	EventDataSubmit    string = "Submitted Data"
    37  	EventReported      string = "Email Reported"
    38  	EventProxyRequest  string = "Proxied request"
    39  	StatusSuccess      string = "Success"
    40  	StatusQueued       string = "Queued"
    41  	StatusSending      string = "Sending"
    42  	StatusUnknown      string = "Unknown"
    43  	StatusScheduled    string = "Scheduled"
    44  	StatusRetry        string = "Retrying"
    45  	Error              string = "Error"
    46  )
    47  
    48  // Flash is used to hold flash information for use in templates.
    49  type Flash struct {
    50  	Type    string
    51  	Message string
    52  }
    53  
    54  // Response contains the attributes found in an API response
    55  type Response struct {
    56  	Message string      `json:"message"`
    57  	Success bool        `json:"success"`
    58  	Data    interface{} `json:"data"`
    59  }
    60  
    61  // Copy of auth.GenerateSecureKey to prevent cyclic import with auth library
    62  func generateSecureKey() string {
    63  	k := make([]byte, 32)
    64  	io.ReadFull(rand.Reader, k)
    65  	return fmt.Sprintf("%x", k)
    66  }
    67  
    68  func chooseDBDriver(name, openStr string) goose.DBDriver {
    69  	d := goose.DBDriver{Name: name, OpenStr: openStr}
    70  
    71  	switch name {
    72  	case "mysql":
    73  		d.Import = "github.com/go-sql-driver/mysql"
    74  		d.Dialect = &goose.MySqlDialect{}
    75  
    76  	// Default database is sqlite3
    77  	default:
    78  		d.Import = "github.com/mattn/go-sqlite3"
    79  		d.Dialect = &goose.Sqlite3Dialect{}
    80  	}
    81  
    82  	return d
    83  }
    84  
    85  // Setup initializes the Conn object
    86  // It also populates the Gophish Config object
    87  func Setup(c *config.Config) error {
    88  	// Setup the package-scoped config
    89  	conf = c
    90  	// Setup the goose configuration
    91  	migrateConf := &goose.DBConf{
    92  		MigrationsDir: conf.MigrationsPath,
    93  		Env:           "production",
    94  		Driver:        chooseDBDriver(conf.DBName, conf.DBPath),
    95  	}
    96  	// Get the latest possible migration
    97  	latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
    98  	if err != nil {
    99  		log.Error(err)
   100  		return err
   101  	}
   102  
   103  	// Register certificates for tls encrypted db connections
   104  	if conf.DBSSLCaPath != "" {
   105  		switch conf.DBName {
   106  		case "mysql":
   107  			rootCertPool := x509.NewCertPool()
   108  			pem, err := ioutil.ReadFile(conf.DBSSLCaPath)
   109  			if err != nil {
   110  				log.Error(err)
   111  				return err
   112  			}
   113  			if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
   114  				log.Error("Failed to append PEM.")
   115  				return err
   116  			}
   117  			mysql.RegisterTLSConfig("ssl_ca", &tls.Config{
   118  				RootCAs: rootCertPool,
   119  			})
   120  			// Default database is sqlite3, which supports no tls, as connection
   121  			// is file based
   122  		default:
   123  		}
   124  	}
   125  
   126  	// Open our database connection
   127  	i := 0
   128  	for {
   129  		db, err = gorm.Open(conf.DBName, conf.DBPath)
   130  		if err == nil {
   131  			break
   132  		}
   133  		if err != nil && i >= MaxDatabaseConnectionAttempts {
   134  			log.Error(err)
   135  			return err
   136  		}
   137  		i += 1
   138  		log.Warn("waiting for database to be up...")
   139  		time.Sleep(5 * time.Second)
   140  	}
   141  	db.LogMode(false)
   142  	db.SetLogger(log.Logger)
   143  	db.DB().SetMaxOpenConns(1)
   144  	if err != nil {
   145  		log.Error(err)
   146  		return err
   147  	}
   148  	// Migrate up to the latest version
   149  	err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
   150  	if err != nil {
   151  		log.Error(err)
   152  		return err
   153  	}
   154  	// Create the admin user if it doesn't exist
   155  	var userCount int64
   156  	db.Model(&User{}).Count(&userCount)
   157  	adminRole, err := GetRoleBySlug(RoleAdmin)
   158  	if err != nil {
   159  		log.Error(err)
   160  		return err
   161  	}
   162  	if userCount == 0 {
   163  		initUser := User{
   164  			Username: "admin",
   165  			Hash:     "$2a$10$IYkPp0.QsM81lYYPrQx6W.U6oQGw7wMpozrKhKAHUBVL4mkm/EvAS", //gophish
   166  			Role:     adminRole,
   167  			RoleID:   adminRole.ID,
   168  		}
   169  		initUser.ApiKey = generateSecureKey()
   170  		err = db.Save(&initUser).Error
   171  		if err != nil {
   172  			log.Error(err)
   173  			return err
   174  		}
   175  	}
   176  	return nil
   177  }