From e149cf59239121b6ead27f0e7ea7127a77b8c992 Mon Sep 17 00:00:00 2001 From: mayankmittal-iitr Date: Sat, 4 Dec 2021 01:56:57 +0530 Subject: [PATCH] parent 7c76667000c81e3b79309fea53c38ed9c0ac17ee author mayankmittal-iitr 1638563217 +0530 committer Mayank Mittal 1642515212 +0530 Add flag submission service --- .gitignore | 2 +- config.sample.toml | 5 + configs/parser.go | 2 + configs/types.go | 7 ++ go.mod | 1 + go.sum | 5 + lib/mongo/constants.go | 14 +++ lib/mongo/read.go | 80 ++++++++++++++ lib/utils/ssh.go | 55 ++++++++++ services/flaghandlerservice/controller.go | 47 +++++++++ services/flaghandlerservice/cronjob.go | 51 +++++++++ services/flaghandlerservice/random.go | 36 +++++++ services/flaghandlerservice/server.go | 123 ++++++++++++++++++++++ services/flaghandlerservice/statements.go | 35 ++++++ services/sshproviderservice/helper.go | 1 + services/sshproviderservice/server.go | 22 +++- types/mongo.go | 32 +++++- 17 files changed, 510 insertions(+), 8 deletions(-) create mode 100644 lib/utils/ssh.go create mode 100644 services/flaghandlerservice/cronjob.go create mode 100644 services/flaghandlerservice/random.go create mode 100644 services/flaghandlerservice/server.go create mode 100644 services/flaghandlerservice/statements.go diff --git a/.gitignore b/.gitignore index 6e71ba44..7b97719d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ tmp/* katana test.go vendor/* -*.log +*.log \ No newline at end of file diff --git a/config.sample.toml b/config.sample.toml index 80473a91..50706ae1 100644 --- a/config.sample.toml +++ b/config.sample.toml @@ -50,3 +50,8 @@ url = "mongodb://scar:scar@localhost:27017/?authSource=admin" [admin] username = "sdslabs" password = "sdslabs" + +[flag] +flaglength = 10 +tickperiod = 300 +submissionport = 4040 \ No newline at end of file diff --git a/configs/parser.go b/configs/parser.go index 55b18d29..dcd71081 100644 --- a/configs/parser.go +++ b/configs/parser.go @@ -36,4 +36,6 @@ var ( TeamVmConfig = KatanaConfig.TeamVmConfig MongoConfig = KatanaConfig.Mongo + + FlagConfig = KatanaConfig.FlagConfig ) diff --git a/configs/types.go b/configs/types.go index 76876348..3a5d5338 100644 --- a/configs/types.go +++ b/configs/types.go @@ -52,6 +52,12 @@ type MongoCfg struct { URL string `toml:"url"` } +type FlagCfg struct { + FlagLength int `toml:"flaglength"` + TickPeriod uint `toml:"tickperiod"` + SubmissionServicePort string `toml:"submissionport"` +} + type KatanaCfg struct { KubeHost string `toml:"kubehost"` KubeNameSpace string `toml:"kubenamespace"` @@ -62,4 +68,5 @@ type KatanaCfg struct { Mongo MongoCfg `toml:"mongo"` TeamVmConfig TeamChallengeConfig `toml:"teamvm"` AdminConfig AdminCfg `toml:"admin"` + FlagConfig FlagCfg `toml:"flag"` } diff --git a/go.mod b/go.mod index c460752c..50efb224 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/gofiber/fiber/v2 v2.1.0 github.com/golang/protobuf v1.4.3 github.com/googleapis/gnostic v0.5.3 // indirect + github.com/jasonlvhit/gocron v0.0.1 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/sirupsen/logrus v1.6.0 github.com/spf13/cobra v1.0.0 diff --git a/go.sum b/go.sum index 5c4ebe8f..f5131625 100644 --- a/go.sum +++ b/go.sum @@ -107,6 +107,7 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+ github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -201,6 +202,8 @@ github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU= +github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -260,6 +263,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -400,6 +404,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= diff --git a/lib/mongo/constants.go b/lib/mongo/constants.go index 33104a75..01b4b582 100644 --- a/lib/mongo/constants.go +++ b/lib/mongo/constants.go @@ -10,4 +10,18 @@ const ( UsernameKey = "username" PasswordKey = "password" + + FlagsCollection = "flags" + + ChallengesCollection = "challenges" + + SubmissionsCollection = "submissions" + + ValueKey = "value" + + IDKey = "id" + + SubmittedBy = "submittedby" + + Flag = "flag" ) diff --git a/lib/mongo/read.go b/lib/mongo/read.go index d70717b8..6214c368 100644 --- a/lib/mongo/read.go +++ b/lib/mongo/read.go @@ -43,3 +43,83 @@ func FetchSingleTeam(teamName string) (*types.CTFTeam, error) { } return team, nil } + +func FetchFlag(flagValue string) (*types.Flag, error) { + collection := link.Collection(FlagsCollection) + flag := &types.Flag{} + ctx := context.Background() + if err := collection.FindOne(ctx, bson.M{ValueKey: flagValue}).Decode(flag); err != nil { + return nil, err + } + return flag, nil +} + +func FetchChallenge(challengeId int) (*types.Challenge, error) { + collection := link.Collection(ChallengesCollection) + challenge := &types.Challenge{} + ctx := context.Background() + if err := collection.FindOne(ctx, bson.M{IDKey: challengeId}).Decode(challenge); err != nil { + return nil, err + } + return challenge, nil +} + +func FetchTeams(ctx context.Context, collectionName string, filter bson.M, opts ...*options.FindOptions) []types.CTFTeam { + collection := link.Collection(collectionName) + var data []types.CTFTeam + + cur, err := collection.Find(ctx, filter, opts...) + if err != nil { + log.Println(err.Error()) + return nil + } + defer cur.Close(ctx) + for cur.Next(ctx) { + var result types.CTFTeam + if err := cur.Decode(&result); err != nil { + log.Println(err.Error()) + return nil + } + data = append(data, result) + } + if err := cur.Err(); err != nil { + log.Println(err) + return nil + } + return data +} + +func FetchChallenges(ctx context.Context, collectionName string, filter bson.M, opts ...*options.FindOptions) []types.Challenge { + collection := link.Collection(collectionName) + var data []types.Challenge + + cur, err := collection.Find(ctx, filter, opts...) + if err != nil { + log.Println(err.Error()) + return nil + } + defer cur.Close(ctx) + for cur.Next(ctx) { + var result types.Challenge + if err := cur.Decode(&result); err != nil { + log.Println(err.Error()) + return nil + } + data = append(data, result) + } + if err := cur.Err(); err != nil { + log.Println(err) + return nil + } + return data +} + +func FetchSubmission(teamId int, flag string) (*types.Submission, error) { + collection := link.Collection(SubmissionsCollection) + submission := &types.Submission{} + ctx := context.Background() + if err := collection.FindOne(ctx, bson.M{SubmittedBy: teamId, Flag: flag}).Decode(submission); err != nil { + return nil, err + } + return submission, nil +} diff --git a/lib/utils/ssh.go b/lib/utils/ssh.go new file mode 100644 index 00000000..d2db8d1f --- /dev/null +++ b/lib/utils/ssh.go @@ -0,0 +1,55 @@ +package utils + +import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "golang.org/x/crypto/ssh" + "strings" +) + +func CheckPrivateKey(privateKey, publicKey string) bool { + //check key + pub, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey)) + if err != nil { + fmt.Println("error in parsing public key") + return false + } + + private, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { + fmt.Println("error in parsing private key") + return false + } + + return bytes.Equal(private.PublicKey().Marshal(), pub.Marshal()) +} + +func GenerateSSHKeyPair() (string, string, error) { + privateKey, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + return "", "", err + } + + // generate and write private key as PEM + var privKeyBuf strings.Builder + + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + if err := pem.Encode(&privKeyBuf, privateKeyPEM); err != nil { + return "", "", err + } + + // generate and write public key + pub, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return "", "", err + } + + var pubKeyBuf strings.Builder + pubKeyBuf.Write(ssh.MarshalAuthorizedKey(pub)) + + return pubKeyBuf.String(), privKeyBuf.String(), nil +} diff --git a/services/flaghandlerservice/controller.go b/services/flaghandlerservice/controller.go index 11aad807..1f39a8a8 100644 --- a/services/flaghandlerservice/controller.go +++ b/services/flaghandlerservice/controller.go @@ -1 +1,48 @@ package flaghandlerservice + +import ( + "context" + "time" + + "github.com/sdslabs/katana/lib/mongo" + "github.com/sdslabs/katana/types" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" +) + +func checkSubmission(submission *types.Submission) bool { + _, err := mongo.FetchSubmission(submission.SubmittedBy, submission.Flag) + return err != nil +} + +func submitFlag(value string, team types.CTFTeam) (bool, int) { + flag, err := mongo.FetchFlag(value) + var points int + if err != nil { + return false, 0 + } + if flag.TeamID == team.Index { + return false, 0 + } + submission := &types.Submission{} + submission.ChallengeID = flag.ChallengeID + submission.Flag = flag.Value + submission.SubmittedBy = team.Index + submission.Time = time.Now() + if !checkSubmission(submission) { + return false, 0 + } + if res, err := mongo.FetchChallenge(flag.ChallengeID); err != nil { + return false, 0 + } else { + team.Score = team.Score + res.Points + points = res.Points + } + if err := mongo.UpdateOne(context.Background(), mongo.TeamsCollection, bson.M{"id": team.Index}, team, options.FindOneAndUpdate().SetUpsert(false)); err != nil { + return false, 0 + } + if _, err := mongo.InsertOne(context.Background(), mongo.SubmissionsCollection, submission); err != nil { + return false, 0 + } + return true, points +} diff --git a/services/flaghandlerservice/cronjob.go b/services/flaghandlerservice/cronjob.go new file mode 100644 index 00000000..c96aa23a --- /dev/null +++ b/services/flaghandlerservice/cronjob.go @@ -0,0 +1,51 @@ +package flaghandlerservice + +import ( + "context" + "log" + "sync" + "time" + + "github.com/jasonlvhit/gocron" + "github.com/sdslabs/katana/configs" + "github.com/sdslabs/katana/lib/mongo" + "github.com/sdslabs/katana/types" + "go.mongodb.org/mongo-driver/bson" +) + +func Ticker(wg sync.WaitGroup) { + log.Println("Ticker") + defer wg.Done() + handler() + gocron.Every(uint64(configs.FlagConfig.TickPeriod)).Second().Do(handler) + <-gocron.Start() + // gocron.Every(uint64(configs.FlagConfig.TickPeriod)).Second().Do(flaggetter) todo:trigger setter here + // <-gocron.Start() +} + +func handler() { + log.Print("Handler triggered -> ", time.Now()) + challenges := mongo.FetchChallenges(context.Background(), mongo.ChallengesCollection, bson.M{}) + teams := mongo.FetchTeams(context.Background(), mongo.TeamsCollection, bson.M{}) + time := time.Now() + for _, team := range teams { + for _, challenge := range challenges { + go flagUpdater(challenge, team, time) + } + } +} + +func flagUpdater(challenge types.Challenge, team types.CTFTeam, triggerTime time.Time) { + flagValue := random(configs.FlagConfig.FlagLength) + var flag = &types.Flag{} + flag.Value = flagValue + flag.ChallengeID = challenge.ID + flag.CreatedAt = triggerTime + flag.TeamID = team.Index + if _, err := mongo.InsertOne(context.Background(), mongo.FlagsCollection, flag); err != nil { + log.Println(err) + } else { + log.Println("Trigger setter") + //todo : trigger flag setter here + } +} diff --git a/services/flaghandlerservice/random.go b/services/flaghandlerservice/random.go new file mode 100644 index 00000000..96b325f8 --- /dev/null +++ b/services/flaghandlerservice/random.go @@ -0,0 +1,36 @@ +package flaghandlerservice + +import ( + "bytes" + "crypto/rand" + "encoding/binary" +) + +func Bytes(n int) []byte { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + return b +} + +var defLetters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func random(n int, letters ...string) string { + var letterRunes []rune + if len(letters) == 0 { + letterRunes = defLetters + } else { + letterRunes = []rune(letters[0]) + } + + var bb bytes.Buffer + bb.Grow(n) + l := uint32(len(letterRunes)) + // on each loop, generate one random rune and append to output + for i := 0; i < n; i++ { + bb.WriteRune(letterRunes[binary.BigEndian.Uint32(Bytes(4))%l]) + } + return bb.String() +} diff --git a/services/flaghandlerservice/server.go b/services/flaghandlerservice/server.go new file mode 100644 index 00000000..d8186530 --- /dev/null +++ b/services/flaghandlerservice/server.go @@ -0,0 +1,123 @@ +package flaghandlerservice + +import ( + "fmt" + "log" + "net" + "regexp" + "strconv" + "sync" + + "github.com/sdslabs/katana/configs" + "github.com/sdslabs/katana/lib/mongo" + "github.com/sdslabs/katana/lib/utils" + "github.com/sdslabs/katana/types" +) + +func Server(wg sync.WaitGroup) { + ln, err := net.Listen("tcp", configs.FlagConfig.SubmissionServicePort) + if err != nil { + log.Fatal(ServiceFail, err) + } + defer func() { + ln.Close() + wg.Done() + }() + log.Println(ServiceSuccess, configs.FlagConfig.SubmissionServicePort) + connectedTeam := types.CTFTeam{} + + for { + conn, err := ln.Accept() + if err != nil { + fmt.Println(err) + if err := conn.Close(); err != nil { + log.Println(ClosingError, err) + } + continue + } + + log.Println(Connected, conn.RemoteAddr()) + go handleConnection(conn, connectedTeam) + } +} + +func handleConnection(conn net.Conn, connectedTeam types.CTFTeam) { + defer func() { + if err := conn.Close(); err != nil { + log.Println(ClosingError, err) + } + }() + writeToCient(conn, InitInstruction) + + for { + cmdLine := make([]byte, (1024 * 4)) + n, err := conn.Read(cmdLine) + + if n == 0 || err != nil { + log.Println(ReadError, err) + return + } + + cmd, param, password := parseCommand(string(cmdLine[0:n])) + + if cmd == "" { + writeToCient(conn, InvalidCommand) + continue + } + switch cmd { + case "init": + if param == "" || password == "" { + writeToCient(conn, InvalidParams) + continue + } else if (types.CTFTeam{}) != connectedTeam { + writeToCient(conn, TeamAlreadyExists) + continue + } else { + if condition, team := checkTeam(param, password); condition { + connectedTeam = team + writeToCient(conn, TeamConnected) + continue + } else { + writeToCient(conn, InvalidCreds) + continue + } + } + case "exit": + return + + default: + if (types.CTFTeam{}) == connectedTeam { + writeToCient(conn, NoLogin) + } else if status, points := submitFlag(cmd, connectedTeam); status { + connectedTeam.Score = connectedTeam.Score + points + writeToCient(conn, SubmitSuccess+strconv.Itoa(points)+TotalScore+strconv.Itoa(connectedTeam.Score)+"\n") + } else { + writeToCient(conn, InvalidFlag) + } + } + } +} +func parseCommand(cmdLine string) (cmd, param, password string) { + r, _ := regexp.Compile("(init|exit|[A-Za-z0-9]+)([[:blank:]]([A-Za-z0-9]+)[[:blank:]]([A-Za-z0-9]+))?") + matched := r.FindStringSubmatchIndex(cmdLine) + if matched[6] == -1 { + return cmdLine[matched[2]:matched[3]], "", "" + } + return cmdLine[matched[2]:matched[3]], cmdLine[matched[6]:matched[7]], cmdLine[matched[8]:matched[9]] +} +func checkTeam(teamName string, password string) (bool, types.CTFTeam) { + team := &types.CTFTeam{} + if team, err := mongo.FetchSingleTeam(teamName); err == nil { + if utils.CompareHashWithPassword(team.Password, password) { + return true, *team + } + } + return false, *team +} + +func writeToCient(conn net.Conn, message string) { + if _, err := conn.Write([]byte(message)); err != nil { + log.Println(WriteError, err) + return + } +} diff --git a/services/flaghandlerservice/statements.go b/services/flaghandlerservice/statements.go new file mode 100644 index 00000000..0828b712 --- /dev/null +++ b/services/flaghandlerservice/statements.go @@ -0,0 +1,35 @@ +package flaghandlerservice + +const ( + ServiceFail = "Failed to start flag submision service" + + ServiceSuccess = "Flag Submission Service Started at port " + + Connected = "Connected to" + + ClosingError = "Failed to close\n" + + ReadError = "Connection Read error\n" + + InitInstruction = "Connected to Flag Submission Service\nInitiate your session by `init `\n" + + InvalidCommand = "Invalid Command\n" + + InvalidParams = "Invalid Login Parameters \n" + + TeamAlreadyExists = "Team is already Logged in\n" + + TeamConnected = "Team successfully connected,\nEnter flags to submit them\n" + + InvalidCreds = "Invalid Team Credentials\n" + + SubmitSuccess = "Flag submitted successfully, points: " + + InvalidFlag = "Invalid FLag\n" + + NoLogin = "Please login Team first \n" + + WriteError = "Failed To Write" + + TotalScore = " Total Score: " +) diff --git a/services/sshproviderservice/helper.go b/services/sshproviderservice/helper.go index d486b8cd..9de1cb98 100644 --- a/services/sshproviderservice/helper.go +++ b/services/sshproviderservice/helper.go @@ -35,6 +35,7 @@ func createTeams() error { Name: pod.Name, PodName: pod.Name, Password: hashed, + Score: 0, } fmt.Fprintf(credsFile, "Team: %d, Username: %s, Password: %s\n", i, team.Name, pwd) teams = append(teams, team) diff --git a/services/sshproviderservice/server.go b/services/sshproviderservice/server.go index cef4f7d6..21cfa80a 100644 --- a/services/sshproviderservice/server.go +++ b/services/sshproviderservice/server.go @@ -1,6 +1,7 @@ package sshproviderservice import ( + "bytes" "fmt" "log" "net" @@ -66,11 +67,26 @@ func passwordHandler(s ssh.Context, password string) bool { return utils.CompareHashWithPassword(team.Password, password) } +func publicKeyHandler(s ssh.Context, key ssh.PublicKey) bool { + team, err := mongo.FetchSingleTeam(s.User()) + if err != nil { + return false + } + + publicKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(team.PublicKey)) + if err != nil { + return false + } + + return bytes.Equal(publicKey.Marshal(), key.Marshal()) +} + func Server() *ssh.Server { return &ssh.Server{ - Addr: net.JoinHostPort(g.SSHProviderConfig.Host, fmt.Sprintf("%d", g.SSHProviderConfig.Port)), - Handler: sessionHandler, - PasswordHandler: passwordHandler, + Addr: net.JoinHostPort(g.SSHProviderConfig.Host, fmt.Sprintf("%d", g.SSHProviderConfig.Port)), + Handler: sessionHandler, + PasswordHandler: passwordHandler, + PublicKeyHandler: publicKeyHandler, } } diff --git a/types/mongo.go b/types/mongo.go index 6dc18e2d..cd1c7d1a 100644 --- a/types/mongo.go +++ b/types/mongo.go @@ -1,13 +1,37 @@ package types +import "time" + type AdminUser struct { Username string `json:"username" bson:"username" binding:"required" ` Password string `json:"password" bson:"password" binding:"required"` } type CTFTeam struct { - Index int `json:"id" bson:"password" binding:"required"` - Name string `json:"name" bson:"username" binding:"required"` - PodName string `json:"podname" bson:"podname" binding:"required"` - Password string `json:"password" bson:"password" binding:"required"` + Index int `json:"id" bson:"id" binding:"required"` + Name string `json:"name" bson:"username" binding:"required"` + PodName string `json:"podname" bson:"podname" binding:"required"` + Password string `json:"password" bson:"password" binding:"required"` + PublicKey string `json:"publicKey" bson:"publicKey" binding:"required"` // TODO : initialize + Score int `json:"score" bson:"score" binding:"required"` +} + +type Challenge struct { + ID int `json:"id" bson:"id" binding:"required"` + Name string `json:"name" bson:"name" binding:"required"` + Points int `json:"points" bson:"points" binding:"required"` +} + +type Flag struct { + Value string `json:"value" bson:"value" binding:"required"` + ChallengeID int `json:"challengeid" bson:"challengeid" binding:"required"` + TeamID int `json:"teamid" bson:"teamid" binding:"required"` + CreatedAt time.Time `json:"createtime" bson:"createtime" binding:"required"` +} + +type Submission struct { + SubmittedBy int `json:"submittedby" bson:"submittedby" binding:"required"` + ChallengeID int `json:"challengeid" bson:"challengeid" binding:"required"` + Flag string `json:"flag" bson:"flag" binding:"required"` + Time time.Time `json:"time" bson:"time" binding:"required"` }