(host string)
| 147 | } |
| 148 | |
| 149 | func (c *SSHClientImpl) dialHost(host string) (*ssh.Client, func(), error) { |
| 150 | targetConfig, err := c.buildClientConfig(c.username, c.authValue, c.keyPath) |
| 151 | if err != nil { |
| 152 | return nil, nil, err |
| 153 | } |
| 154 | |
| 155 | addr := fmt.Sprintf("%s:%d", host, c.port) |
| 156 | |
| 157 | if c.jumpHost.Addr == "" { |
| 158 | crSSHLogger().Debug("SSH exec: direct dial host=%s port=%d", host, c.port) |
| 159 | client, err := ssh.Dial("tcp", addr, targetConfig) |
| 160 | if err != nil { |
| 161 | return nil, nil, fmt.Errorf("failed to connect to %s: %w", addr, err) |
| 162 | } |
| 163 | return client, nil, nil |
| 164 | } |
| 165 | |
| 166 | jumpUser := c.jumpHost.User |
| 167 | if jumpUser == "" { |
| 168 | jumpUser = c.username |
| 169 | } |
| 170 | |
| 171 | jumpConfig, err := c.buildClientConfig(jumpUser, "", c.jumpHost.KeyPath) |
| 172 | if err != nil { |
| 173 | return nil, nil, fmt.Errorf("failed to configure jump host: %w", err) |
| 174 | } |
| 175 | |
| 176 | jumpPort := c.jumpHost.Port |
| 177 | if jumpPort == 0 { |
| 178 | jumpPort = c.port |
| 179 | } |
| 180 | jumpAddr := fmt.Sprintf("%s:%d", c.jumpHost.Addr, jumpPort) |
| 181 | crSSHLogger().Debug("SSH exec: dial via jump host=%s user=%s target=%s", jumpAddr, jumpUser, addr) |
| 182 | jumpClient, err := ssh.Dial("tcp", jumpAddr, jumpConfig) |
| 183 | if err != nil { |
| 184 | return nil, nil, fmt.Errorf("failed to connect to jump host %s: %w", jumpAddr, err) |
| 185 | } |
| 186 | |
| 187 | conn, err := jumpClient.Dial("tcp", addr) |
| 188 | if err != nil { |
| 189 | _ = jumpClient.Close() |
| 190 | return nil, nil, fmt.Errorf("failed to connect to %s via jump host: %w", addr, err) |
| 191 | } |
| 192 | |
| 193 | clientConn, chans, reqs, err := ssh.NewClientConn(conn, addr, targetConfig) |
| 194 | if err != nil { |
| 195 | _ = jumpClient.Close() |
| 196 | return nil, nil, fmt.Errorf("failed to establish tunneled SSH connection to %s: %w", addr, err) |
| 197 | } |
| 198 | |
| 199 | cleanup := func() { |
| 200 | _ = jumpClient.Close() |
| 201 | } |
| 202 | |
| 203 | return ssh.NewClient(clientConn, chans, reqs), cleanup, nil |
| 204 | } |
| 205 | |
| 206 | // loadSSHKeys returns SSH signers from all available sources in priority order: |
no test coverage detected