From b1aa5e1f215fc2015c11007ecedae5f7ff21570c Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Fri, 9 Mar 2018 15:14:32 -0500 Subject: [PATCH] Validate ssh keys as they are entered in the profile In particular, reject ssh-dss keys here. They don't work anymore since an upgrade, for security reasons, but there was not really a way for the user to know why. With this they will at least know if when they try to save or change the keys. --- pgweb/core/models.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/pgweb/core/models.py b/pgweb/core/models.py index 20269bcb..8dfef50a 100644 --- a/pgweb/core/models.py +++ b/pgweb/core/models.py @@ -1,7 +1,10 @@ from django.db import models +from django.core.validators import ValidationError from django.contrib.auth.models import User from pgweb.util.misc import varnish_purge +import base64 + TESTING_CHOICES = ( (0, 'Release'), (1, 'Release candidate'), @@ -162,10 +165,30 @@ class ImportedRSSItem(models.Model): return self.posttime.strftime("%Y-%m-%d") +# From man sshd, except for ssh-dss +_valid_keytypes = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'ssh-rsa'] +# Options, keytype, key, comment. But we don't support options. +def validate_sshkey(key): + lines = key.splitlines() + for k in lines: + pieces = k.split() + if len(pieces) == 0: + raise ValidationError("Empty keys are not allowed") + if len(pieces) > 3: + raise ValidationError('Paste each ssh key without options, e.g. "ssh-rsa AAAAbbbcc mykey@machine"') + if pieces[0] == 'ssh-dss': + raise ValidationError("For security reasons, ssh-dss keys are not supported") + if pieces[0] not in _valid_keytypes: + raise ValidationError("Only keys of types {0} are supported, not {1}.".format(", ".join(_valid_keytypes), pieces[0])) + try: + base64.b64decode(pieces[1]) + except: + raise ValidationError("Incorrect base64 encoded key!") + # Extra attributes for users (if they have them) class UserProfile(models.Model): user = models.OneToOneField(User, null=False, blank=False, primary_key=True) - sshkey = models.TextField(null=False, blank=True, verbose_name="SSH key", help_text= "Paste one or more public keys in OpenSSH format, one per line.") + sshkey = models.TextField(null=False, blank=True, verbose_name="SSH key", help_text= "Paste one or more public keys in OpenSSH format, one per line.", validators=[validate_sshkey, ]) lastmodified = models.DateTimeField(null=False, blank=False, auto_now=True) # Notifications sent for any moderated content. -- 2.39.5