136 lines
3.2 KiB
Go
136 lines
3.2 KiB
Go
|
package adlin
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"errors"
|
||
|
"os/exec"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type StudentKey struct {
|
||
|
Id int64 `json:"id"`
|
||
|
IdStudent int64 `json:"id_student"`
|
||
|
Key string `json:"key"`
|
||
|
Time time.Time `json:"time"`
|
||
|
}
|
||
|
|
||
|
func GetStudentKeys() (keys []StudentKey, err error) {
|
||
|
if rows, errr := DBQuery("SELECT id_key, id_student, sshkey, time FROM student_keys"); errr != nil {
|
||
|
return nil, errr
|
||
|
} else {
|
||
|
defer rows.Close()
|
||
|
|
||
|
for rows.Next() {
|
||
|
var k StudentKey
|
||
|
if err = rows.Scan(&k.Id, &k.IdStudent, &k.Key, &k.Time); err != nil {
|
||
|
return
|
||
|
}
|
||
|
keys = append(keys, k)
|
||
|
}
|
||
|
if err = rows.Err(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s Student) GetKeys() (keys []StudentKey, err error) {
|
||
|
if rows, errr := DBQuery("SELECT id_key, id_student, sshkey, time FROM student_keys WHERE id_student = ?", s.Id); errr != nil {
|
||
|
return nil, errr
|
||
|
} else {
|
||
|
defer rows.Close()
|
||
|
|
||
|
for rows.Next() {
|
||
|
var k StudentKey
|
||
|
if err = rows.Scan(&k.Id, &k.IdStudent, &k.Key, &k.Time); err != nil {
|
||
|
return
|
||
|
}
|
||
|
keys = append(keys, k)
|
||
|
}
|
||
|
if err = rows.Err(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getStudentKey(id int) (k StudentKey, err error) {
|
||
|
err = DBQueryRow("SELECT id_key, id_student, sshkey, time FROM student_keys WHERE id_key=?", id).Scan(&k.Id, &k.IdStudent, &k.Key, &k.Time)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s Student) NewKey(key string) (k StudentKey, err error) {
|
||
|
// Check key before importing it
|
||
|
cmd := exec.Command("ssh-keygen", "-l", "-f", "-")
|
||
|
cmd.Stdin = strings.NewReader(key)
|
||
|
var stdoutStderr []byte
|
||
|
stdoutStderr, err = cmd.CombinedOutput()
|
||
|
if err != nil {
|
||
|
if _, ok := err.(*exec.ExitError); ok {
|
||
|
err = errors.New(string(stdoutStderr))
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
chunks := bytes.Fields(stdoutStderr)
|
||
|
|
||
|
keytype := string(chunks[len(chunks)-1])
|
||
|
minkeysize := 2048
|
||
|
if keytype == "(ED25519)" || keytype == "(ECDSA)" {
|
||
|
minkeysize = 256
|
||
|
}
|
||
|
|
||
|
var bits int
|
||
|
if bits, err = strconv.Atoi(string(chunks[0])); err != nil {
|
||
|
return
|
||
|
} else if bits < minkeysize {
|
||
|
err = errors.New("Keysize too small")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Sanitize the given key
|
||
|
keyf := strings.Fields(key)
|
||
|
if len(keyf) < 2 {
|
||
|
err = errors.New("Unexpected key file, this should never happen")
|
||
|
return
|
||
|
}
|
||
|
key = keyf[0] + " " + keyf[1]
|
||
|
|
||
|
if res, err := DBExec("INSERT INTO student_keys (id_student, sshkey, time) VALUES (?, ?, ?)", s.Id, key, time.Now()); err != nil {
|
||
|
return StudentKey{}, err
|
||
|
} else if kid, err := res.LastInsertId(); err != nil {
|
||
|
return StudentKey{}, err
|
||
|
} else {
|
||
|
s.UnlockNewChallenge(9, "")
|
||
|
return StudentKey{kid, s.Id, key, time.Now()}, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (k StudentKey) GetStudent() (Student, error) {
|
||
|
return GetStudent(int(k.IdStudent))
|
||
|
}
|
||
|
|
||
|
func (k StudentKey) Update() (int64, error) {
|
||
|
if res, err := DBExec("UPDATE student_keys SET id_student = ?, sshkey = ?, time = ? WHERE id_key = ?", k.IdStudent, k.Key, k.Time, k.Id); err != nil {
|
||
|
return 0, err
|
||
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||
|
return 0, err
|
||
|
} else {
|
||
|
return nb, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (k StudentKey) Delete() (int64, error) {
|
||
|
if res, err := DBExec("DELETE FROM student_keys WHERE id_key = ?", k.Id); err != nil {
|
||
|
return 0, err
|
||
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||
|
return 0, err
|
||
|
} else {
|
||
|
return nb, err
|
||
|
}
|
||
|
}
|