split checker from token-validator
This commit is contained in:
parent
685dc0b0ea
commit
0c661f36f6
20 changed files with 634 additions and 748 deletions
|
@ -15,27 +15,29 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"git.nemunai.re/lectures/adlin/libadlin"
|
||||
)
|
||||
|
||||
const IPgwDMZ = "172.23.200.1"
|
||||
|
||||
type Challenge struct {
|
||||
Accessible []func(*Student, *http.Request) error
|
||||
Check func(*Student, *givenToken, int) error
|
||||
Accessible []func(*adlin.Student, *http.Request) error
|
||||
Check func(*adlin.Student, *givenToken, int) error
|
||||
}
|
||||
|
||||
/* Restrictions */
|
||||
|
||||
func noAccessRestriction(*Student, *http.Request) error {
|
||||
func noAccessRestriction(*adlin.Student, *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func noAccess(*Student, *http.Request) error {
|
||||
func noAccess(*adlin.Student, *http.Request) error {
|
||||
return errors.New("This challenge cannot be accessed this way. ")
|
||||
}
|
||||
|
||||
func accessFrom(ip string) func(_ *Student, r *http.Request) error {
|
||||
return func(_ *Student, r *http.Request) error {
|
||||
func accessFrom(ip string) func(_ *adlin.Student, r *http.Request) error {
|
||||
return func(_ *adlin.Student, r *http.Request) error {
|
||||
if r.Header.Get("X-Forwarded-By") != ip {
|
||||
return errors.New("This challenge is not accessible this way.")
|
||||
}
|
||||
|
@ -43,8 +45,8 @@ func accessFrom(ip string) func(_ *Student, r *http.Request) error {
|
|||
}
|
||||
}
|
||||
|
||||
func notAccessFrom(ip string) func(_ *Student, r *http.Request) error {
|
||||
return func(_ *Student, r *http.Request) error {
|
||||
func notAccessFrom(ip string) func(_ *adlin.Student, r *http.Request) error {
|
||||
return func(_ *adlin.Student, r *http.Request) error {
|
||||
if r.Header.Get("X-Forwarded-By") == ip {
|
||||
return errors.New("This challenge is not accessible this way.")
|
||||
}
|
||||
|
@ -52,8 +54,8 @@ func notAccessFrom(ip string) func(_ *Student, r *http.Request) error {
|
|||
}
|
||||
}
|
||||
|
||||
func maxProxy(nb int) func(_ *Student, r *http.Request) error {
|
||||
return func(_ *Student, r *http.Request) error {
|
||||
func maxProxy(nb int) func(_ *adlin.Student, r *http.Request) error {
|
||||
return func(_ *adlin.Student, r *http.Request) error {
|
||||
if len(strings.Split(r.Header.Get("X-Forwarded-For"), ",")) > nb {
|
||||
return errors.New("This challenge is not accessible this way.")
|
||||
}
|
||||
|
@ -61,50 +63,49 @@ func maxProxy(nb int) func(_ *Student, r *http.Request) error {
|
|||
}
|
||||
}
|
||||
|
||||
func sslOnly(_ *Student, r *http.Request) error {
|
||||
func sslOnly(_ *adlin.Student, r *http.Request) error {
|
||||
if r.Header.Get("X-Forwarded-Proto") != "https" {
|
||||
return errors.New("This challenge should be performed over TLS.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
/* Challenges */
|
||||
|
||||
func challenge42(s *Student, t *givenToken, chid int) error {
|
||||
func challenge42(s *adlin.Student, t *givenToken, chid int) error {
|
||||
pkey := s.GetPKey()
|
||||
if expectedToken, err := GenerateToken(pkey, chid, []byte("42")); err != nil {
|
||||
return err
|
||||
} else if ! hmac.Equal(expectedToken, t.token) {
|
||||
} else if !hmac.Equal(expectedToken, t.token) {
|
||||
return errors.New("This is not the expected token.")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func challengeDNS(s *Student, t *givenToken, chid int) error {
|
||||
func challengeDNS(s *adlin.Student, t *givenToken, chid int) error {
|
||||
pkey := s.GetPKey()
|
||||
if expectedToken, err := GenerateToken(pkey, chid, []byte("8dde678132d6c558fc6adaeb9f1d53bf6ec7b876308cf98c48604caa9138523c1ce58b672c87c7e7d9b7248b81804d3940dbf20bf263eeb683244f7c1143712d")); err != nil {
|
||||
return err
|
||||
} else if ! hmac.Equal(expectedToken, t.token) {
|
||||
} else if !hmac.Equal(expectedToken, t.token) {
|
||||
return errors.New("This is not the expected token.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func challengeTime(s *Student, t *givenToken, chid int) error {
|
||||
func challengeTime(s *adlin.Student, t *givenToken, chid int) error {
|
||||
pkey := s.GetPKey()
|
||||
if expectedToken, err := GenerateToken(pkey, chid, []byte(t.Data[0])); err != nil {
|
||||
return err
|
||||
} else if ! hmac.Equal(expectedToken, t.token) {
|
||||
} else if !hmac.Equal(expectedToken, t.token) {
|
||||
return errors.New("This is not the expected token.")
|
||||
} else if t, err := strconv.ParseInt(t.Data[0], 10, 64); err != nil {
|
||||
return err
|
||||
} else {
|
||||
var rt time.Time
|
||||
if t > 3000000000 {
|
||||
rt = time.Unix(t / 1000000000, t % 1000000000)
|
||||
rt = time.Unix(t/1000000000, t%1000000000)
|
||||
} else {
|
||||
rt = time.Unix(t, 0)
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ func challengeTime(s *Student, t *givenToken, chid int) error {
|
|||
}
|
||||
}
|
||||
|
||||
func challengePing(s *Student, t *givenToken, chid int) error {
|
||||
func challengePing(s *adlin.Student, t *givenToken, chid int) error {
|
||||
var expected []byte
|
||||
switch s.Id % 5 {
|
||||
case 1:
|
||||
|
@ -164,7 +165,7 @@ func challengePing(s *Student, t *givenToken, chid int) error {
|
|||
}
|
||||
}
|
||||
|
||||
func challengeDisk(s *Student, t *givenToken, chid int) error {
|
||||
func challengeDisk(s *adlin.Student, t *givenToken, chid int) error {
|
||||
pkey := fmt.Sprintf("%x", s.GetPKey())
|
||||
|
||||
n1, err := strconv.Atoi(t.Data[0][0:2])
|
||||
|
@ -182,19 +183,19 @@ func challengeDisk(s *Student, t *givenToken, chid int) error {
|
|||
}
|
||||
|
||||
if n1+n2 > len(pkey) {
|
||||
n2 = len(pkey)-n1
|
||||
n2 = len(pkey) - n1
|
||||
}
|
||||
|
||||
expectedToken := sha512.Sum512([]byte(pkey[n1:n1+n2]))
|
||||
expectedToken := sha512.Sum512([]byte(pkey[n1 : n1+n2]))
|
||||
|
||||
if ! hmac.Equal(expectedToken[:], sum) {
|
||||
if !hmac.Equal(expectedToken[:], sum) {
|
||||
return errors.New("This is not the expected token.")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func challengeEMail(s *Student, t *givenToken, chid int) error {
|
||||
func challengeEMail(s *adlin.Student, t *givenToken, chid int) error {
|
||||
return errors.New("This is not the expected token.")
|
||||
}
|
||||
|
||||
|
@ -204,61 +205,61 @@ func init() {
|
|||
challenges = []Challenge{
|
||||
/* Challenge 1 : 42 */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challenge42,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challenge42,
|
||||
},
|
||||
|
||||
/* Challenge 2 : 42 from DMZ */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{accessFrom(IPgwDMZ)},
|
||||
Check: challenge42,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{accessFrom(IPgwDMZ)},
|
||||
Check: challenge42,
|
||||
},
|
||||
|
||||
/* Challenge 3 : ssl (+ ntp) */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{accessFrom(IPgwDMZ), sslOnly},
|
||||
Check: challengeTime,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{accessFrom(IPgwDMZ), sslOnly},
|
||||
Check: challengeTime,
|
||||
},
|
||||
|
||||
/* Challenge 4 : DNS TXT */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{accessFrom(IPgwDMZ), sslOnly},
|
||||
Check: challengeDNS,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{accessFrom(IPgwDMZ), sslOnly},
|
||||
Check: challengeDNS,
|
||||
},
|
||||
|
||||
/* Challenge 5 : time net */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{maxProxy(1)},
|
||||
Check: challengeTime,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{maxProxy(1)},
|
||||
Check: challengeTime,
|
||||
},
|
||||
|
||||
/* Bonus 0 : toctoc (read in source code) */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challenge42,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challenge42,
|
||||
},
|
||||
|
||||
/* Bonus 1 : echo request */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengePing,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengePing,
|
||||
},
|
||||
|
||||
/* Bonus 2 : disk */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengeDisk,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengeDisk,
|
||||
},
|
||||
|
||||
/* Bonus 3 : mail */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengeEMail,
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccessRestriction},
|
||||
Check: challengeEMail,
|
||||
},
|
||||
|
||||
/* Last : SSH key, see ssh.go:156 in NewKey function */
|
||||
Challenge{
|
||||
Accessible: []func(*Student, *http.Request) error{noAccess},
|
||||
Accessible: []func(*adlin.Student, *http.Request) error{noAccess},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -272,9 +273,9 @@ func init() {
|
|||
}
|
||||
|
||||
type givenToken struct {
|
||||
Login string `json:"login"`
|
||||
Challenge int `json:"challenge"`
|
||||
Token string `json:"token"`
|
||||
Login string `json:"login"`
|
||||
Challenge int `json:"challenge"`
|
||||
Token string `json:"token"`
|
||||
token []byte
|
||||
Data []string `json:"data"`
|
||||
}
|
||||
|
@ -293,7 +294,7 @@ func accessibleChallenge(r *http.Request, ps httprouter.Params, _ []byte) (inter
|
|||
} 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-1].Accessible {
|
||||
if err := a(nil, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -319,13 +320,13 @@ func receiveChallenge(r *http.Request, ps httprouter.Params, body []byte) (inter
|
|||
return nil, errors.New("This is not the expected token.")
|
||||
}
|
||||
|
||||
var std Student
|
||||
var std adlin.Student
|
||||
|
||||
if stdid, err := strconv.Atoi(gt.Login); err == nil {
|
||||
if std, err = getStudent(stdid); err != nil {
|
||||
if std, err = adlin.GetStudent(stdid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if std, err = getStudentByLogin(gt.Login); err != nil {
|
||||
} else if std, err = adlin.GetStudentByLogin(gt.Login); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -355,21 +356,21 @@ 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-1 > 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-1].Accessible {
|
||||
if err := a(nil, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if std, err := getStudentByLogin(gt.Login); err != nil {
|
||||
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-1].Check(&std, >, chid); err != nil {
|
||||
log.Printf("%s just try ch#%d: %s\n", std.Login, chid, err)
|
||||
return nil, err
|
||||
}
|
||||
|
|
Reference in a new issue