From 01b6315b996c49e15cdadf2d8fc36605414e6d21 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 22 Feb 2020 23:05:54 +0000 Subject: [PATCH] can create users with passwords --- server/db/db.go | 5 ++ server/db/sqlite.go | 55 ++++++++++++++++++++++ server/db/users.go | 6 +++ server/go.mod | 4 +- server/go.sum | 9 ++++ server/main.go | 110 ++++++++++++++++++++++++++++++++++---------- server/request.go | 6 ++- server/server.go | 2 + 8 files changed, 171 insertions(+), 26 deletions(-) create mode 100644 server/db/db.go create mode 100644 server/db/sqlite.go create mode 100644 server/db/users.go diff --git a/server/db/db.go b/server/db/db.go new file mode 100644 index 0000000..2aa191f --- /dev/null +++ b/server/db/db.go @@ -0,0 +1,5 @@ +package db + +type DB struct { + Users +} diff --git a/server/db/sqlite.go b/server/db/sqlite.go new file mode 100644 index 0000000..2f9455d --- /dev/null +++ b/server/db/sqlite.go @@ -0,0 +1,55 @@ +package db + +import ( + "database/sql" + "fmt" + "os" + + _ "github.com/mattn/go-sqlite3" + "golang.org/x/crypto/bcrypt" +) + +type SQLite struct { + db *sql.DB +} + +func OpenSQLite(path string) (*SQLite, error) { + db, err := sql.Open("sqlite3", path) + if err != nil { + return nil, fmt.Errorf("unable to open sqlite3 database at %s: %v", path, err) + } + + if _, err := db.Exec(` + create table if not exists users ( + id integer primary key autoincrement, + name text unique not null, + phash text not null, + psalt text not null + );`); err != nil { + fmt.Fprintf(os.Stderr, "failed to create users table: %v\n", err) + } + + return &SQLite{db: db}, nil +} + +func (db *SQLite) CreateUser(name, pass, salt string) error { + combined := []byte(pass + salt) + hashBytes, err := bcrypt.GenerateFromPassword(combined, 13) + if err != nil { + return fmt.Errorf("unable to generate password hash: %v", err) + } + hash := string(hashBytes) + if _, err := db.db.Exec(` + insert into users (name, phash, psalt) + values (?, ?, ?); + `, name, hash, salt); err != nil { + return fmt.Errorf("unable to insert user: %v", err) + } + return nil +} + +func (db *SQLite) CheckPassword(name, pass string) error { + return nil +} + +func (db *SQLite) Close() error { return db.db.Close() } diff --git a/server/db/users.go b/server/db/users.go new file mode 100644 index 0000000..542b89e --- /dev/null +++ b/server/db/users.go @@ -0,0 +1,6 @@ +package db + +type Users interface { + CreateUser(name, pass string) error + CheckPassword(name, pass string) error +} diff --git a/server/go.mod b/server/go.mod index 5700757..86e1e67 100644 --- a/server/go.mod +++ b/server/go.mod @@ -6,6 +6,8 @@ require ( github.com/gorilla/mux v1.7.3 github.com/gorilla/websocket v1.4.1 github.com/jordanorelli/blammo v0.0.0-20200201231725-9fd70eb7c1f2 + github.com/mattn/go-sqlite3 v2.0.3+incompatible + github.com/prometheus/common v0.4.0 github.com/spf13/cobra v0.0.6 - golang.org/x/crypto v0.0.0-20200117160349-530e935923ad // indirect + golang.org/x/crypto v0.0.0-20200117160349-530e935923ad ) diff --git a/server/go.sum b/server/go.sum index 8dd6621..ffcf581 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,7 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -57,6 +59,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -70,6 +74,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -77,6 +82,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -100,6 +106,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -118,6 +125,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -128,6 +136,7 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/server/main.go b/server/main.go index 40adcf9..9826529 100644 --- a/server/main.go +++ b/server/main.go @@ -1,48 +1,110 @@ package main import ( + "crypto/rand" + "fmt" "net" "net/http" "os" "github.com/jordanorelli/blammo" + "github.com/jordanorelli/kloam/db" "github.com/spf13/cobra" ) +func cryptostring(n int) string { + b := make([]byte, n) + rand.Read(b) + letters := `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%*-=+` + r := make([]byte, 0, n) + for _, n := range b { + r = append(r, letters[int(n)%len(letters)]) + } + return string(r) +} + +func runServer(cmd *cobra.Command, args []string) { + stdout := blammo.NewLineWriter(os.Stdout) + stderr := blammo.NewLineWriter(os.Stderr) + log := blammo.NewLog("kloam", blammo.DebugWriter(stdout), blammo.InfoWriter(stdout), blammo.ErrorWriter(stderr)) + + conn, err := db.OpenSQLite(cmd.Flag("db").Value.String()) + if err != nil { + log.Error("unable to open sqlite database: %v", err) + os.Exit(1) + } + defer conn.Close() + + s := server{ + Log: log, + db: conn, + join: make(chan player), + leave: make(chan *player), + inbox: make(chan message), + souls: make(map[string]soul), + } + s.init() + go s.run() + lis, err := net.Listen("tcp", cmd.Flag("listen").Value.String()) + if err != nil { + log.Error("listen error: %v", err) + return + } + log.Info("listening on %v", lis.Addr()) + http.Serve(lis, s.handler()) +} + +func runUserCreate(cmd *cobra.Command, args []string) { + conn, err := db.OpenSQLite(cmd.Flag("db").Value.String()) + if err != nil { + fmt.Fprintf(os.Stderr, "unable to open sqlite database: %v\n", err) + } + defer conn.Close() + + user := args[0] + var pass string + if len(args) > 1 { + pass = args[1] + } else { + pass = cryptostring(12) + } + salt := cryptostring(12) + + if err := conn.CreateUser(user, pass, salt); err != nil { + fmt.Fprintf(os.Stderr, "failed to create user: %v\n", err) + return + } + + fmt.Printf("created:\n\tuser:\t%s\n\tpass:\t%s\n", user, pass) +} + func main() { cmd := &cobra.Command{ Use: "kloam", } + cmd.PersistentFlags().String("db", "./kloam.sqlite3", "path to a sqlite3 file to use as a database") server := &cobra.Command{ Use: "server", Short: "the kloam multiplayer server", - Run: func(cmd *cobra.Command, args []string) { - stdout := blammo.NewLineWriter(os.Stdout) - stderr := blammo.NewLineWriter(os.Stderr) - log := blammo.NewLog("kloam", blammo.DebugWriter(stdout), blammo.InfoWriter(stdout), blammo.ErrorWriter(stderr)) - - s := server{ - Log: log, - join: make(chan player), - leave: make(chan *player), - inbox: make(chan message), - souls: make(map[string]soul), - } - s.init() - go s.run() - lis, err := net.Listen("tcp", cmd.Flag("listen").Value.String()) - if err != nil { - log.Error("listen error: %v", err) - return - } - log.Info("listening on %v", lis.Addr()) - http.Serve(lis, s.handler()) - }, + Run: runServer, } server.Flags().StringP("listen", "l", "0.0.0.0:9001", "ip:port to listen on") - cmd.AddCommand(server) - cmd.Execute() + user := &cobra.Command{ + Use: "user", + Short: "user management stuff", + } + cmd.AddCommand(user) + + userCreate := &cobra.Command{ + Use: "create", + Short: "create a user", + Args: cobra.RangeArgs(1, 2), + Run: runUserCreate, + } + user.AddCommand(userCreate) + + cmd.Execute() } diff --git a/server/request.go b/server/request.go index e41d5ce..d8fd46a 100644 --- a/server/request.go +++ b/server/request.go @@ -69,7 +69,11 @@ type login struct { } func (l *login) exec(s *server, from *player) { - from.username = l.Username + if err := s.db.CheckPassword(l.Username, l.Password); err != nil { + from.username = l.Username + } else { + + } } type death struct { diff --git a/server/server.go b/server/server.go index d758c62..82a9d6d 100644 --- a/server/server.go +++ b/server/server.go @@ -9,6 +9,7 @@ import ( "github.com/gorilla/mux" "github.com/gorilla/websocket" "github.com/jordanorelli/blammo" + "github.com/jordanorelli/kloam/db" ) type server struct { @@ -19,6 +20,7 @@ type server struct { leave chan *player inbox chan message souls map[string]soul + db *db.SQLite } func (s *server) init() {