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 }