checker: integrate student checker script into token-validator

This commit is contained in:
nemunaire 2020-03-27 13:09:54 +01:00
parent 709205846e
commit 63e39f8b03
3 changed files with 133 additions and 9 deletions

122
token-validator/checker.go Normal file
View File

@ -0,0 +1,122 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/miekg/dns"
"github.com/sparrc/go-ping"
)
// ICMP
func check_ping(ip string, cb func(pkt *ping.Packet)) (err error) {
var pinger *ping.Pinger
pinger, err = ping.NewPinger(ip)
if err != nil {
return
}
pinger.Timeout = time.Second * 5
pinger.Count = 1
pinger.OnRecv = cb
pinger.SetPrivileged(true)
pinger.Run()
return
}
func (s *Student) onPong(state bool) (err error) {
_, err = DBExec("INSERT INTO student_pong (id_student, time, state) VALUES (?, ?, ?)", s.Id, time.Now(), state)
return
}
// PORT 53
func check_dns(domain, ip string) (err error) {
client := dns.Client{Timeout: time.Second * 5}
m := new(dns.Msg)
m.SetQuestion(domain, dns.TypeSOA)
_, _, err = client.Exchange(m, fmt.Sprintf("[%s]:53", ip))
return
}
// PORT 80
func check_http(ip string) (err error) {
var resp *http.Response
resp, err = http.Get(fmt.Sprintf("http://[%s]/", ip))
if err != nil {
return
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
return
}
// PORT 443
func check_https(domain, ip string) (err error) {
var resp *http.Response
resp, err = http.Get(fmt.Sprintf("https://%s/", domain))
if err != nil {
return
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
return
}
// Main
func studentsChecker() {
students, err := getStudents()
if err != nil {
log.Println("Unable to check students:", err)
return
}
for _, s := range students {
time.Sleep(250 * time.Millisecond)
// Check ping
std := s
stdIP := studentIP(std.Id).String() + "1"
go check_ping(stdIP, func(pkt *ping.Packet) {
std.onPong(true)
// Check HTTP
if err := check_http(stdIP); err == nil {
if _, err := std.UnlockNewChallenge(100, ""); err != nil {
if _, err := std.UpdateUnlockedChallenge(100, ""); err != nil {
log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error())
}
}
}
// Check HTTPs
if err := check_https(std.myAssociatedDomain(), stdIP); err == nil {
if _, err := std.UnlockNewChallenge(101, ""); err != nil {
if _, err := std.UpdateUnlockedChallenge(101, ""); err != nil {
log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error())
}
}
}
// Check DNS
if err := check_dns(std.MyDelegatedDomain(), stdIP); err == nil {
if _, err := std.UnlockNewChallenge(102, ""); err != nil {
if _, err := std.UpdateUnlockedChallenge(102, ""); err != nil {
log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error())
}
}
}
return
})
}
}

View File

@ -12,6 +12,7 @@ import (
"path"
"strings"
"syscall"
"time"
)
var baseURL string = "/"
@ -106,6 +107,14 @@ func main() {
Handler: StripPrefix(baseURL, Router()),
}
// Launch checker
go func() {
for {
studentsChecker()
time.Sleep(500 * time.Millisecond)
}
}()
// Serve content
go func() {
log.Fatal(srv.ListenAndServe())

View File

@ -10,7 +10,7 @@ var PongSecret = "felixfixit"
func init() {
router.GET("/api/students/:sid/ping", apiHandler(studentHandler(lastPing)))
router.GET("/api/students/:sid/pong", apiHandler(studentHandler(func (student Student, body []byte) (interface{}, error) {
router.GET("/api/students/:sid/pong", apiHandler(studentHandler(func(student Student, body []byte) (interface{}, error) {
return student.lastPongs()
})))
router.POST("/api/students/:sid/pong", apiHandler(studentHandler(stdPong), sslOnly))
@ -62,12 +62,5 @@ func stdPong(student Student, body []byte) (interface{}, error) {
return nil, errors.New("This is not the expected token.")
}
if res, err := DBExec("INSERT INTO student_pong (id_student, time, state) VALUES (?, ?, ?)", student.Id, time.Now(), gt.Challenge == 0); err != nil {
return false, err
} else if _, err := res.LastInsertId(); err != nil {
return false, err
} else {
return true, err
}
return true, student.onPong(gt.Challenge == 0)
}