This repository has been archived on 2024-03-03. You can view files and clone it, but cannot push or open issues or pull requests.
adlin/token-validator/remote-challenge.go

124 lines
2.7 KiB
Go

package main
import (
"bytes"
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"time"
"github.com/julienschmidt/httprouter"
"git.nemunai.re/srs/adlin/libadlin"
)
func init() {
router.POST("/remote", rawHandler(responseHandler(remoteChallHandler(receiveRemoteChallenge))))
}
type SendMeta struct {
Time time.Time `json:"time"`
Login string `json:"login"`
Test string `json:"test"`
}
type SendContent struct {
Meta []byte `json:"meta"`
Data []byte `json:"data"`
Sign []byte `json:"sign"`
Key []byte `json:"key"`
KeySign []byte `json:"keysign"`
}
func remoteChallHandler(f func(*http.Request, *adlin.Student, SendContent) (interface{}, error)) func(*http.Request, httprouter.Params, []byte) (interface{}, error) {
return func(r *http.Request, ps httprouter.Params, body []byte) (v interface{}, err error) {
var data SendContent
err = json.Unmarshal(body, &data)
if err != nil {
return
}
// Check signatures
if !ed25519.Verify(adlin.GetCollectorPublic(), data.Key, data.KeySign) {
return nil, fmt.Errorf("Bad KSK signature")
}
if !ed25519.Verify(data.Key, append(data.Meta, data.Data...), data.Sign) {
return nil, fmt.Errorf("Bad DSK signature")
}
var meta SendMeta
err = json.NewDecoder(base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(data.Meta))).Decode(&meta)
if err != nil {
return
}
// Find pubkeys associated with login
var std *adlin.Student
std, err = adlin.GetStudentByLogin(string(meta.Login))
if err != nil {
return
}
var tps []ed25519.PublicKey
tps, err = std.GetActivesTunnelsPubKey()
if err != nil {
return
}
// Check signature
found := false
for _, pubk := range tps {
if pubk.Equal(ed25519.PublicKey(data.Key)) {
found = true
break
}
}
if !found {
return nil, fmt.Errorf("Unable to find key for user")
}
return f(r, std, data)
}
}
func receiveRemoteChallenge(r *http.Request, std *adlin.Student, data SendContent) (interface{}, error) {
var tests map[string]*string
err := json.NewDecoder(base64.NewDecoder(base64.StdEncoding, bytes.NewBuffer(data.Data))).Decode(&tests)
if err != nil {
return nil, err
}
for k, v := range tests {
var chalid int
switch k {
case "wks-cm1":
chalid = 210
case "wks-dg1":
chalid = 209
case "wks-rh1":
chalid = 208
case "wks-rh2":
chalid = 208
}
if chalid != 0 {
if v == nil {
if _, err := std.UnlockChallenge(chalid, ""); err != nil {
log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error())
}
} else if errreg := std.RegisterChallengeError(chalid, errors.New(*v)); errreg != nil {
log.Printf("Unable to register challenge error for %s: %s\n", std.Login, errreg)
}
}
}
return true, err
}