From 9eaa2bf4e861470dc13159a0edb4cc010ee19c50 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Thu, 28 Feb 2019 09:41:10 +0100 Subject: [PATCH] token-validator: check key before importing it --- token-validator/ssh.go | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/token-validator/ssh.go b/token-validator/ssh.go index e8d9448..cd271da 100644 --- a/token-validator/ssh.go +++ b/token-validator/ssh.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "crypto/hmac" "encoding/json" "encoding/hex" @@ -10,14 +11,16 @@ import ( "log" "net/http" "os" + "os/exec" "path" "strconv" + "strings" "time" "github.com/julienschmidt/httprouter" ) -var AuthorizedKeysLocation = "/var/lib/adlin/.ssh/authorized_keys" +var AuthorizedKeysLocation = "/root/.ssh/authorized_keys" var SshPiperLocation = "/var/sshpiper/" func init() { @@ -100,6 +103,42 @@ func getStudentKey(id int) (k StudentKey, err error) { } 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 { @@ -212,7 +251,7 @@ func dumpAuthorizedKeysFile(w io.Writer) { } s, _ := k.GetStudent() - w.Write([]byte("command=\"/adlin.sh " + fmt.Sprintf("%d", k.IdStudent) + " '" + s.Login + "'\",no-pty,no-agent-forwarding,no-port-forwarding ssh-ed25519 " + k.Key + fmt.Sprintf(" Student#%d-%q\n", k.IdStudent, s.Login))) + w.Write([]byte("command=\"/root/adlin.sh " + fmt.Sprintf("%d", k.IdStudent) + " '" + s.Login + "'\",restrict " + k.Key + fmt.Sprintf(" Student#%d-%q\n", k.IdStudent, s.Login))) } } } @@ -229,7 +268,7 @@ func (s Student) dumpAuthorizedKeysFile(w io.Writer) { } s, _ := k.GetStudent() - w.Write([]byte("ssh-ed25519 " + k.Key + fmt.Sprintf(" Student#%d-%q\n", k.IdStudent, s.Login))) + w.Write([]byte(k.Key + fmt.Sprintf(" Student#%d-%q\n", k.IdStudent, s.Login))) } } }