@@ -22,6 +22,7 @@ import (
2222 "fmt"
2323 "time"
2424
25+ chssh "github.com/ClickHouse/ch-go/ssh"
2526 "github.com/ClickHouse/clickhouse-go/v2/lib/proto"
2627)
2728
@@ -79,6 +80,61 @@ func (c *connect) handshake(auth Auth) error {
7980 c .debugf ("[handshake] downgrade client proto" )
8081 }
8182 c .debugf ("[handshake] <- %s" , c .server )
83+
84+ // Handle SSH authentication if configured
85+ if c .opt .SSHKeyFile != "" {
86+ if err := c .performSSHAuthentication (); err != nil {
87+ return err
88+ }
89+ }
90+
91+ return nil
92+ }
93+
94+ func (c * connect ) performSSHAuthentication () error {
95+ // Load SSH key
96+ sshKey , err := chssh .LoadPrivateKeyFromFile (c .opt .SSHKeyFile , c .opt .SSHKeyPassphrase )
97+ if err != nil {
98+ return fmt .Errorf ("failed to load SSH key: %w" , err )
99+ }
100+
101+ // Send SSH challenge request
102+ c .buffer .Reset ()
103+ c .buffer .PutByte (proto .ClientSSHChallengeRequest )
104+ if err := c .flush (); err != nil {
105+ return fmt .Errorf ("send SSH challenge request: %w" , err )
106+ }
107+
108+ // Read SSH challenge response
109+ packet , err := c .reader .ReadByte ()
110+ if err != nil {
111+ return fmt .Errorf ("read SSH challenge response: %w" , err )
112+ }
113+
114+ if packet != proto .ServerSSHChallenge {
115+ return fmt .Errorf ("unexpected packet [%d] from server during SSH authentication" , packet )
116+ }
117+
118+ // Read challenge string
119+ challenge , err := c .reader .Str ()
120+ if err != nil {
121+ return fmt .Errorf ("read SSH challenge string: %w" , err )
122+ }
123+
124+ // Sign the challenge
125+ signature , err := sshKey .SignString (challenge )
126+ if err != nil {
127+ return fmt .Errorf ("sign SSH challenge: %w" , err )
128+ }
129+
130+ // Send SSH challenge response
131+ c .buffer .Reset ()
132+ c .buffer .PutByte (proto .ClientSSHChallengeResponse )
133+ c .buffer .PutString (signature )
134+ if err := c .flush (); err != nil {
135+ return fmt .Errorf ("send SSH challenge response: %w" , err )
136+ }
137+
82138 return nil
83139}
84140
0 commit comments