Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support options for authorized SSH keys #54

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions ssh_ldap_pubkey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,76 @@
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'''

def parse_key(pubkey):
"""Split an SSH public key into its components.

Keys can have the form:
[options] keytype keydata [keyname/comment]

Arguments:
pubkey (str) The string to parse.
Returns:
tuple: A tuple of the parsed components containing

- keytype (str): the ssh key type.
- data64 (str): the base64 encoded data.
- comment (str or None): the keyname/comment data. None if not present.
- options (str or None): the ssh key options. None if not present.
Raises:
ValueError: if pubkey cannot be parsed to a public key.
"""
valid_keytypes = [
"ssh-dss",
"ssh-rsa",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"ssh-ed25519",
]

# As the options field may contain spaces (within quoted strings) the
# parsing is not trivial. The strategy here is to find the key type field.
# Anything before it can be recombined into the options. The field
# immediately after must be the key data and the oen after that the comment.
comps = pubkey.split()

# Locate the key type field as an anchor point
for keytype_ind, key_type in enumerate(comps):
if key_type in valid_keytypes:
break
else:
raise ValueError("public key does not contain valid key type.")

# Recombine the key options
if comps[:keytype_ind]:
options = " ".join(comps[:keytype_ind])
else:
options = None
comps = comps[(keytype_ind + 1):]

# Get out the data field
if comps:
data64 = comps.pop(0)
else:
raise ValueError("Key does not contain a data field.")

# Get the optional comment
if comps:
comment = comps[0]
else:
comment = None

return (key_type, data64, comment, options)


def keyname(pubkey):
return pubkey.split()[-1]
comment = parse_key(pubkey)[2]

if comment is None:
# Return the data as the keyname to match the previous behaviour
return data64
else:
return comment


def is_valid_openssh_pubkey(pubkey):
Expand All @@ -34,7 +101,7 @@ def is_valid_openssh_pubkey(pubkey):
bool: `True` if the given string is a valid key, `False` otherwise.
"""
try:
key_type, data64 = map(_encode, pubkey.split()[0:2])
key_type, data64 = map(_encode, parse_key(pubkey)[:2])
except (ValueError, AttributeError):
return False
try:
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/valid_ssh_keys
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCkNCKyyUPvwwefhEpnD/Khuowbv+13Cv3shWY3ck3j+hbHLqjCGUB66/igg0Atf3giU7sZOdPrSN6xdX43+k6Gn73yzWFJkWyImKzgHW9uVrU7vo3puailY+yC6RpwNME= flynn@encom.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCkNCKyyUPvwwefhEpnD/Khuowbv+13Cv3shWY3ck3j+hbHLqjCGUB66/igg0Atf3giU7sZOdPrSN6xdX43+k6Gn73yzWFJkWyImKzgHW9uVrU7vo3puailY+yC6RpwNME=
ssh-dss AAAAB3NzaC1kc3MAAACBAKMfNb7OtqUc5vje5UMvm5r1javDreL+EvACyU7N/BqO+FnqYx6RWQgp0mgDW5b+eOVBBwCfqn41TKHoXIlOsD3Rci7REBA87jmRbgQnZLSaT6BgVFWtEMI8SXG3EsmC5fXKHfX8j6W6f0Tuqeof4eaFW2RC6pYN3rvVGCvJ68FXAAAAFQDbmXw8U17CkJDvFOZ8KqehrahunQAAAIAKg/NxJVqLTJOM6qp7zI0WOiStotzclC5899w3zqJ446P/jLD5nILpnhbnUHnGmw53Yz6endWKHInsUurODPRZcjgOOd2lG5/RViegrI81YsQtczzIRNU86xL/28UkzzAy1IMeJWiH2vSrLLzx37YKZFH4MBjPhlsFtEIfHeR3dQAAAIEAlAMlPaHMIMEP+4IQP3qUhcZhI8UIYlSag2DqRjPry9jRL6uaYUYZAPC82Bvfi83TqJEhowqIBDFib4HDrgp9BJyTGfDZsHjRcLP15FYQdqIg8Fdo2ptsWGJa6EdFmj8RDIyaHsQ4a/JtnHUu+nC7DMYvTHliWl55UUVCSJzAyzs=
command="bbcp SRC",no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCkNCKyyUPvwwefhEpnD/Khuowbv+13Cv3shWY3ck3j+hbHLqjCGUB66/igg0Atf3giU7sZOdPrSN6xdX43+k6Gn73yzWFJkWyImKzgHW9uVrU7vo3puailY+yC6RpwNME= flynn@encom.com
command="bbcp SRC",no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCkNCKyyUPvwwefhEpnD/Khuowbv+13Cv3shWY3ck3j+hbHLqjCGUB66/igg0Atf3giU7sZOdPrSN6xdX43+k6Gn73yzWFJkWyImKzgHW9uVrU7vo3puailY+yC6RpwNME=