grim/convey
Clone
Summary
Browse
Changes
Graph
Add documentation for extend task.
2017-09-20, Eric Fritz
a4b424d543a1
Add documentation for extend task.
/*
* Convey
* Copyright 2016-2017 Gary Kramlich <grim@reaperworld.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package
ssh
import
(
"fmt"
"io"
"net"
"os"
"strings"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
// KeysAvailable returns True if there is at least one key that the ssh agent
// knows about, otherwise false. err will be set if there is an error along
// the way.
func
KeysAvailable
(
identites
[]
string
)
(
bool
,
error
)
{
sshAgent
,
err
:=
net
.
Dial
(
"unix"
,
os
.
Getenv
(
"SSH_AUTH_SOCK"
))
if
err
!=
nil
{
return
false
,
err
}
return
keysAvailable
(
sshAgent
,
identites
)
}
func
keysAvailable
(
rw
io
.
ReadWriter
,
identities
[]
string
)
(
bool
,
error
)
{
keys
,
err
:=
agent
.
NewClient
(
rw
).
List
()
if
err
!=
nil
{
return
false
,
err
}
// this runs in O(m * n) but thankful the number of keys should be low.
for
_
,
identity
:=
range
identities
{
if
identity
==
"*"
{
// if the user doesn't care which key and we have a key, return true
if
len
(
keys
)
>
0
{
return
true
,
nil
}
else
{
// if the user doesn't care which key but we have no keys, return an error
return
false
,
fmt
.
Errorf
(
"no ssh keys available"
)
}
}
uIdentity
:=
strings
.
ToUpper
(
identity
)
for
_
,
pubKey
:=
range
keys
{
fpSHA256
:=
strings
.
ToUpper
(
ssh
.
FingerprintSHA256
(
pubKey
))
fpMD5
:=
strings
.
ToUpper
(
ssh
.
FingerprintLegacyMD5
(
pubKey
))
if
strings
.
HasPrefix
(
uIdentity
,
"SHA256:"
)
{
if
uIdentity
==
fpSHA256
{
return
true
,
nil
}
}
else
if
strings
.
HasPrefix
(
uIdentity
,
"MD5:"
)
{
if
uIdentity
[
4
:]
==
fpMD5
{
return
true
,
nil
}
}
else
{
// no known prefix check sha256 then md5, then give up
if
uIdentity
==
fpSHA256
[
7
:]
||
uIdentity
==
fpMD5
{
return
true
,
nil
}
}
}
}
if
err
==
nil
{
err
=
fmt
.
Errorf
(
"no usable ssh identities found"
)
}
return
false
,
err
}
func
ShouldEnable
(
identities
[]
string
)
(
bool
,
error
)
{
if
len
(
identities
)
<=
0
{
return
false
,
nil
}
haveKeys
,
err
:=
KeysAvailable
(
identities
)
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"error talking to ssh-agent: %s"
,
err
)
}
if
!
haveKeys
{
return
false
,
fmt
.
Errorf
(
"no keys available in ssh-agent"
)
}
return
true
,
nil
}