Home » Questions » Computers [ Ask a new question ]

How can I get the comment of the current authorized_keys ssh key?

How can I get the comment of the current authorized_keys ssh key?

Edit: What I really need to know WHICH ssh key from authorized_keys has been used to identify the currently logged on user.

Asked by: Guest | Views: 258
Total answers/comments: 2
Guest [Entry]

"It's for convenience, from the ssh-keygen man page on Debian:

For RSA1 keys, there is also a comment field in the key file that is
only for convenience to the user to
help identify
the key. The comment can tell what the key is for, or whatever is
useful. The comment is initialized to
“user@host”
when the key is created, but can be changed using the -c option.

I think the nearest you're going to get for determining which key was used to log in is with ssh-add, with -L, from the man page:

-L Lists public key parameters of all identities currently represented by the agent.

You can increase the logging level of the ssh daemon to DEBUG1:

LogLevel DEBUG1

And the log will show the RSA fingerprint of the SSH key used to log in:

Aug 13 08:52:56 ubuntu_test sshd[17115]: debug1: matching key found: file /home/username/.ssh/authorized_keys, line 1
Aug 13 08:52:56 ubuntu_test sshd[17115]: Found matching RSA key: xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx

You can get the fingerprint of a key with ssh-keygen:

-l Show fingerprint of specified public key file. Private RSA1 keys are also supported. For RSA
and DSA keys ssh-keygen tries to find the matching public key file and prints its fingerprint.
If combined with -v, an ASCII art representation of the key is supplied with the fingerprint.

From an authorized keys file, you would have to split up each line into a new file to read with ssh-keygen -l. Here's an example Ruby script that will do this:

#!/usr/bin/env ruby
File.open(""/home/username/.ssh/authorized_keys"").each do |l|
file_name = l.split("" "")[2]
key_file = File.new(""#{file_name}.pub_key"", ""w"")
key_file.puts l
key_file.close
puts %x{ssh-keygen -l -f #{file_name}.pub_key}
end"
Guest [Entry]

"I needed the same thing now and wrote a small script that updates the authorized_keys file and adds the environment variable SSH_COMMENT for every key in the file.
If an option with the environment=""SSH_COMMENT=<comment>"" is already there it updates it, all other options remain untouched and in the same order as before. Also the comments remain untouched.
The script also works fine if there are already other options containing spaces. This works by removing one part at a time from the end of a line until only the options remain.
Here is the bash function. It only needs grep, sed, cmp, mv, rm and chmod.
upgradeAuthorized() {
local authorized=""${1-}""

if [ -z ""$authorized"" ]; then
local defaultFile
for defaultFile in ""$HOME/.ssh/authorized_keys"" ""$HOME/.ssh/authorized_keys2""; do
if upgradeAuthorized ""$defaultFile""; then
return 0
fi
done
return 1
fi

if ! [ -f ""$authorized"" ]; then
# Fail silently
return 1
fi

local comment
local line
local key
local keytype
local options
local commentEscaped
local userEnv
local newFile
newFile=""${authorized}.new""
rm -f ""$newFile""

while IFS='' read -r line; do
# Output comments and empty lines as-is
if grep -Eq ""^(\s*|\s*#.*)$"" <<<""$line""; then
echo ""$line"" >> ""${newFile}""
continue
fi

comment=""${line##* }""
line=""${line% *}""
key=""${line##* }""
line=""${line% *}""
keytype=""${line##* }""
options=""${line% *}""
if [[ ""$options"" == ""$keytype"" ]]; then
options=""""
fi

commentSshEscaped=""$(sed ""s/\""/\\\""/g"" <<<""$comment"")""
if grep -Fq ""environment=\""SSH_COMMENT="" <<< ""$options""; then
commentSedEscaped=""$(sedEscapeReplace ""$commentSshEscaped"")""

options=""$(sed -E ""s/(environment=\""SSH_COMMENT=)(.+?)*\""(,.*|$)/\1${commentSedEscaped}\""\3/g"" <<<""$options"")""
elif [ -z ""$options"" ]; then
options=""environment=\""SSH_COMMENT=${commentSshEscaped}\""""
else
options=""environment=\""SSH_COMMENT=${commentSshEscaped}\"",${options}""
fi

echo ""${options} ${keytype} ${key} ${comment}"" >> ""${newFile}""
done < ""$authorized""

if ! cmp -s ""${authorized}"" ""${newFile}""; then
mv -b ""${newFile}"" ""${authorized}""
chmod 0644 ""${authorized}""
else
rm ""${newFile}""
fi
return 0
}

Finally if you want to rerieve the comment from an arbitrary process you are allowed to access the environment, you can use the following function. It outputs the comment for a pid or nothing.
pSshComment() {
local pid=""${1-}""
local default=""${2-}""
if [ -z ""${pid}"" ]; then
echo ""${default}""
return 1
fi

if ! [ -f ""/proc/${pid}/environ"" ]; then
echo ""${default}""
return 1
fi

local comment
comment=""$(xargs -0 printf '%s\n' < ""/proc/${pid}/environ"" 2>/dev/null | sed -nE ""s/^SSH_COMMENT=(.*)$/\1/p"")""
if [ -z ""$comment"" ]; then
return 1
fi
echo ""$comment""
return 0
}"