1
0
mirror of https://github.com/lxc/incus.git synced 2026-02-05 09:46:19 +01:00
Files
incus/cmd/incus-user/proxy.go
Maciek Borzecki 576f7cf4d0 cmd/incus-user: keep track of socket path used to connect to the server
The logic used to figure out the correct Unix socket path for access to
 the demon in `client.ConnectIncusUnix()` was fixed in in
 d8b78d5007 to account for use of
 /run/incus/unix.socket as an alternative socket location. However, the
 proxying code of incus-user was not updated when the fix was
 introduced. As a result, even if initial connection to the server and
 the configuration queries were successful, the actual attempt to proxy
 a client request would fail while trying to connect to
 /var/lib/incus/unix.socket regardless of prior findings.

Signed-off-by: Maciek Borzecki <maciek.borzecki@gmail.com>
2025-01-25 17:29:39 +01:00

137 lines
3.1 KiB
Go

package main
import (
"crypto/tls"
"fmt"
"io"
"net"
"os"
"slices"
log "github.com/sirupsen/logrus"
"github.com/lxc/incus/v6/internal/linux"
internalUtil "github.com/lxc/incus/v6/internal/util"
localtls "github.com/lxc/incus/v6/shared/tls"
"github.com/lxc/incus/v6/shared/util"
)
func tlsConfig(uid uint32) (*tls.Config, error) {
// Load the client certificate.
content, err := os.ReadFile(internalUtil.VarPath("users", fmt.Sprintf("%d", uid), "client.crt"))
if err != nil {
return nil, fmt.Errorf("Unable to open client certificate: %w", err)
}
tlsClientCert := string(content)
// Load the client key.
content, err = os.ReadFile(internalUtil.VarPath("users", fmt.Sprintf("%d", uid), "client.key"))
if err != nil {
return nil, fmt.Errorf("Unable to open client key: %w", err)
}
tlsClientKey := string(content)
// Load the server certificate.
certPath := internalUtil.VarPath("cluster.crt")
if !util.PathExists(certPath) {
certPath = internalUtil.VarPath("server.crt")
}
content, err = os.ReadFile(certPath)
if err != nil {
return nil, fmt.Errorf("Unable to open server certificate: %w", err)
}
tlsServerCert := string(content)
return localtls.GetTLSConfigMem(tlsClientCert, tlsClientKey, "", tlsServerCert, false)
}
func proxyConnection(conn *net.UnixConn, serverUnixPath string) {
defer func() {
_ = conn.Close()
mu.Lock()
connections -= 1
mu.Unlock()
}()
// Increase counters.
mu.Lock()
transactions += 1
connections += 1
mu.Unlock()
// Get credentials.
creds, err := linux.GetUcred(conn)
if err != nil {
log.Errorf("Unable to get user credentials: %s", err)
return
}
// Setup logging context.
logger := log.WithFields(log.Fields{
"uid": creds.Uid,
"gid": creds.Gid,
"pid": creds.Pid,
})
logger.Debug("Connected")
defer logger.Debug("Disconnected")
// Check if the user was setup.
if !util.PathExists(internalUtil.VarPath("users", fmt.Sprintf("%d", creds.Uid))) || !slices.Contains(projectNames, fmt.Sprintf("user-%d", creds.Uid)) {
log.Infof("Setting up for uid %d", creds.Uid)
err := serverSetupUser(creds.Uid)
if err != nil {
log.Errorf("Failed to setup new user: %v", err)
return
}
}
// Connect to the daemon.
unixAddr, err := net.ResolveUnixAddr("unix", serverUnixPath)
if err != nil {
log.Errorf("Unable to resolve the target server: %v", err)
return
}
client, err := net.DialUnix("unix", nil, unixAddr)
if err != nil {
log.Errorf("Unable to connect to target server: %v", err)
return
}
defer func() { _ = client.Close() }()
// Get the TLS configuration
tlsConfig, err := tlsConfig(creds.Uid)
if err != nil {
log.Errorf("Failed to load TLS connection settings: %v", err)
return
}
// Setup TLS.
_, err = client.Write([]byte("STARTTLS\n"))
if err != nil {
log.Errorf("Failed to setup TLS connection to target server: %v", err)
return
}
tlsClient := tls.Client(client, tlsConfig)
// Establish the TLS handshake.
err = tlsClient.Handshake()
if err != nil {
_ = conn.Close()
log.Errorf("Failed TLS handshake with target server: %v", err)
return
}
// Start proxying.
go func() { _, _ = io.Copy(conn, tlsClient) }()
_, _ = io.Copy(tlsClient, conn)
}