Pass client SSH key fingerprint in upstream username
When using public key auth, include the client's key fingerprint in the upstream username with format: fp:FINGERPRINT.originaluser This allows upstream servers (like maldoror) to identify users by their original SSH key even when sshpiper uses its own key for upstream authentication.
This commit is contained in:
parent
17c0645dc6
commit
e6667a6b8c
1 changed files with 20 additions and 1 deletions
|
|
@ -2,10 +2,13 @@ package skel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
|
|
@ -253,7 +256,8 @@ func (p *SkelPlugin) PublicKeyCallback(conn libplugin.ConnMetadata, publicKey []
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := p.createUpstream(conn, to, nil)
|
// Pass the client's public key so their fingerprint can be included in the upstream username
|
||||||
|
u, err := p.createUpstreamWithClientKey(conn, to, nil, publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -262,6 +266,10 @@ func (p *SkelPlugin) PublicKeyCallback(conn libplugin.ConnMetadata, publicKey []
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SkelPlugin) createUpstream(conn libplugin.ConnMetadata, to SkelPipeTo, originalPassword []byte) (*libplugin.Upstream, error) {
|
func (p *SkelPlugin) createUpstream(conn libplugin.ConnMetadata, to SkelPipeTo, originalPassword []byte) (*libplugin.Upstream, error) {
|
||||||
|
return p.createUpstreamWithClientKey(conn, to, originalPassword, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SkelPlugin) createUpstreamWithClientKey(conn libplugin.ConnMetadata, to SkelPipeTo, originalPassword []byte, clientPublicKey []byte) (*libplugin.Upstream, error) {
|
||||||
host, port, err := libplugin.SplitHostPortForSSH(to.Host(conn))
|
host, port, err := libplugin.SplitHostPortForSSH(to.Host(conn))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -272,6 +280,17 @@ func (p *SkelPlugin) createUpstream(conn libplugin.ConnMetadata, to SkelPipeTo,
|
||||||
user = conn.User()
|
user = conn.User()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If client public key is provided, prepend fingerprint to username
|
||||||
|
// Format: "SHA256:xxxxx.originaluser" - maldoror/upstream can parse this
|
||||||
|
if clientPublicKey != nil {
|
||||||
|
hash := sha256.Sum256(clientPublicKey)
|
||||||
|
fingerprint := base64.RawStdEncoding.EncodeToString(hash[:])
|
||||||
|
// Replace any dots in fingerprint with underscores to avoid parsing issues
|
||||||
|
fingerprint = strings.ReplaceAll(fingerprint, ".", "_")
|
||||||
|
user = "fp:" + fingerprint + "." + user
|
||||||
|
log.Debugf("passing client fingerprint in username: %s", user)
|
||||||
|
}
|
||||||
|
|
||||||
p.cache.SetDefault(conn.UniqueID(), to)
|
p.cache.SetDefault(conn.UniqueID(), to)
|
||||||
|
|
||||||
u := &libplugin.Upstream{
|
u := &libplugin.Upstream{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue