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 }