From 5de31f10d7e208fafe473668fd1c999c5b76c615 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 20 Feb 2023 12:33:26 +0100 Subject: [PATCH] Add a challenge for shadow password --- pkg/login-validator/cmd/passwd.go | 45 +++++++++++++++++++++++ token-validator/challenge.go | 22 +++++++---- token-validator/htdocs/js/adlin-common.js | 1 + 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/pkg/login-validator/cmd/passwd.go b/pkg/login-validator/cmd/passwd.go index 0eed76d..56dbf5e 100644 --- a/pkg/login-validator/cmd/passwd.go +++ b/pkg/login-validator/cmd/passwd.go @@ -1,7 +1,10 @@ package main import ( + "bytes" "compress/gzip" + "encoding/json" + "fmt" "io" "log" "net/http" @@ -157,6 +160,48 @@ func passwd(w http.ResponseWriter, r *http.Request) { return } + err = RegisterShadowChallenge(initrd) + if err != nil { + log.Printf("%s: Unable to register shadow challenge: %s", r.RemoteAddr, err.Error()) + } + log.Println("Registered shadow for", r.RemoteAddr) http.Error(w, "Success", http.StatusOK) } + +func RegisterShadowChallenge(initrd string) error { + // Retrieve username + fdlogin, err := os.Open(path.Join(tftpDir, "shadows", initrd, "whois")) + if err != nil { + return err + } + defer fdlogin.Close() + + cnt, err := io.ReadAll(fdlogin) + if err != nil { + return err + } + + tmp := bytes.Split(cnt, []byte("\n")) + if len(tmp) < 0 { + return fmt.Errorf("Too few fields in whois file") + } + + login := tmp[0] + + // Register shadow challenge + if j, err := json.Marshal(struct { + Token string + Login string + }{Token: loginSalt, Login: string(login)}); err != nil { + return err + } else if r, err := http.NewRequest("POST", "https://adlin.nemunai.re/challenge/0", bytes.NewReader(j)); err != nil { + return err + } else if resp, err := http.DefaultClient.Do(r); err == nil { + resp.Body.Close() + } else { + return err + } + + return nil +} diff --git a/token-validator/challenge.go b/token-validator/challenge.go index a75a273..4647845 100644 --- a/token-validator/challenge.go +++ b/token-validator/challenge.go @@ -237,6 +237,12 @@ var challenges []Challenge func init() { challenges = []Challenge{ + /* Challenge 0 : shadow updated */ + Challenge{ + Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction}, + Check: challengeOk, + }, + /* Challenge 1 : 42 */ Challenge{ Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction}, @@ -333,10 +339,10 @@ func getChallengeList(_ httprouter.Params, _ []byte) (interface{}, error) { func accessibleChallenge(r *http.Request, ps httprouter.Params, _ []byte) (interface{}, error) { if chid, err := strconv.Atoi(string(ps.ByName("chid"))); err != nil { return nil, err - } else if chid == 0 || chid >= len(challenges) { + } else if chid == 0 || chid > len(challenges) { return nil, errors.New("This challenge doesn't exist") } else { - for _, a := range challenges[chid-1].Accessible { + for _, a := range challenges[chid].Accessible { if err := a(nil, r); err != nil { return nil, err } @@ -345,12 +351,13 @@ func accessibleChallenge(r *http.Request, ps httprouter.Params, _ []byte) (inter } } +// receiveChallenge treats TP1{shadow} and TP2, TP3 challenges. func receiveChallenge(r *http.Request, ps httprouter.Params, body []byte) (interface{}, error) { if chid, err := strconv.Atoi(string(ps.ByName("chid"))); err != nil { return nil, err - } else if chid == 0 { + } else if chid < 0 { return nil, errors.New("This challenge doesn't exist") - } else if chid <= len(challenges) { + } else if chid != 0 && chid <= len(challenges) { return nil, errors.New("This is not the good way to hit this challenge") } else { var gt givenToken @@ -382,6 +389,7 @@ func receiveChallenge(r *http.Request, ps httprouter.Params, body []byte) (inter } } +// receiveToken handles challenges for TP1 except shadow func receiveToken(r *http.Request, body []byte, chid int) (interface{}, error) { var gt givenToken if err := json.Unmarshal(body, >); err != nil { @@ -398,12 +406,12 @@ func receiveToken(r *http.Request, body []byte, chid int) (interface{}, error) { chid = gt.Challenge } - if chid <= 0 || chid-1 > len(challenges) { + if chid <= 0 || chid > len(challenges) { return nil, errors.New("This challenge doesn't exist") } // Is the challenge accessible? - for _, a := range challenges[chid-1].Accessible { + for _, a := range challenges[chid].Accessible { if err := a(nil, r); err != nil { return nil, err } @@ -412,7 +420,7 @@ func receiveToken(r *http.Request, body []byte, chid int) (interface{}, error) { if std, err := adlin.GetStudentByLogin(gt.Login); err != nil { return nil, err } else { - if err := challenges[chid-1].Check(std, >, chid); err != nil { + if err := challenges[chid].Check(std, >, chid); err != nil { log.Printf("%s just try ch#%d: %s\n", std.Login, chid, err) return nil, err } diff --git a/token-validator/htdocs/js/adlin-common.js b/token-validator/htdocs/js/adlin-common.js index 23f49ad..0483f32 100644 --- a/token-validator/htdocs/js/adlin-common.js +++ b/token-validator/htdocs/js/adlin-common.js @@ -13,6 +13,7 @@ const tuto_legend = { const tuto_progress = [ { + 0: { title: "single", icon: "🕵️", label: "Shadow"}, 1: { title: "Is alive?", icon: "👋", label: "Token 1"}, 2: { title: "DMZ reached", icon: "📚", label: "Token 2"}, 3: { title: "HTTPS on + time", icon: "⏲", label: "Token 3"},