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() { 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() { 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) { k = new(StudentKey) 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 nil, err } else if kid, err := res.LastInsertId(); err != nil { return nil, err } else { s.UnlockNewChallenge(11, "") 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 } }