Skip to content

Commit 774b549

Browse files
committed
fix: permissions for wireguard dir
1 parent 469193a commit 774b549

3 files changed

Lines changed: 67 additions & 32 deletions

File tree

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ View available servers and locations:
6060

6161
### Connection Management
6262

63-
Connect to a server:
64-
`sudo mbvpn connect <server>` (or the shorthand `sudo mbvpn c <server>`)
63+
Connect to a server (will request sudo password when needed):
64+
`mbvpn connect <server>` (or the shorthand `mbvpn c <server>`)
6565

66-
Disconnect from VPN:
67-
`sudo mbvpn disconnect` (or the shorthand `sudo mbvpn d`)
66+
Disconnect from VPN (will request sudo password when needed):
67+
`mbvpn disconnect` (or the shorthand `mbvpn d`)
6868

69-
Check connection status:
70-
`sudo mbvpn status`
69+
Check connection status (will request sudo password when needed):
70+
`mbvpn status`
7171

7272
End your session:
7373
`mbvpn logout`
@@ -82,7 +82,7 @@ The `mbvpn logout` command deactivates your device (makes the license seat free)
8282

8383
### Cannot disconnect, lost internet access
8484

85-
Use `sudo mbvpn disconnect` (without specifying a server). The tool will attempt to disconnect from all WireGuard connections.
85+
Use `mbvpn disconnect` (without specifying a server). The tool will attempt to disconnect from all WireGuard connections (will request sudo password when needed).
8686

8787
If that doesn't help, manually disconnect using WireGuard directly:
8888
1. Find your connection: `wg show`

pkg/console/console.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,6 @@ func sanitizeWgConfigPath(cfgPath string, dirProvider config.DirectoryProvider)
8989
return "", fmt.Errorf("failed to resolve absolute path: %w", err)
9090
}
9191

92-
// Verify the file exists and is a regular file
93-
fileInfo, err := os.Stat(absPath)
94-
if err != nil {
95-
return "", fmt.Errorf("config file not accessible: %w", err)
96-
}
97-
98-
if !fileInfo.Mode().IsRegular() {
99-
return "", fmt.Errorf("config path is not a regular file")
100-
}
101-
10292
// Check if it's within the expected config directory OR system wireguard directory
10393
expectedBase, err := dirProvider.GetServersDir()
10494
if err != nil {
@@ -111,10 +101,28 @@ func sanitizeWgConfigPath(cfgPath string, dirProvider config.DirectoryProvider)
111101
}
112102

113103
// Path must be in either user config directory or system wireguard directory
114-
if !strings.HasPrefix(absPath, expectedBase) && !strings.HasPrefix(absPath, wireguardBase) {
104+
inUserDir := strings.HasPrefix(absPath, expectedBase)
105+
inSystemDir := strings.HasPrefix(absPath, wireguardBase)
106+
107+
if !inUserDir && !inSystemDir {
115108
return "", fmt.Errorf("config file must be within %s or %s", expectedBase, wireguardBase)
116109
}
117110

111+
// Verify the file exists and is a regular file
112+
// For system directory (/etc/wireguard), skip this check as regular users
113+
// may not have permission to stat root-owned files with 0600 permissions.
114+
// wg-quick will run with sudo and can access them.
115+
if inUserDir {
116+
fileInfo, err := os.Stat(absPath)
117+
if err != nil {
118+
return "", fmt.Errorf("config file not accessible: %w", err)
119+
}
120+
121+
if !fileInfo.Mode().IsRegular() {
122+
return "", fmt.Errorf("config path is not a regular file")
123+
}
124+
}
125+
118126
// Verify file extension (WireGuard configs must be .conf)
119127
if filepath.Ext(absPath) != ".conf" {
120128
return "", fmt.Errorf("config file must have .conf extension")

pkg/vpn/vpn.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vpn
33
import (
44
"fmt"
55
"os"
6+
"os/exec"
67
"path/filepath"
78
"strings"
89

@@ -426,28 +427,54 @@ func (vpn *DefaultVpn) saveWgConfig(serverName string, configContent string) (st
426427
}
427428

428429
// copyConfigToSystem copies a config file from user directory to /etc/wireguard
429-
// This requires sudo permissions and is called during connection operations.
430+
// Uses sudo for operations requiring elevated privileges in production.
431+
// In test environments, uses direct file operations.
430432
func (vpn *DefaultVpn) copyConfigToSystem(userConfigPath, serverName string) (string, error) {
431433
wireguardDir, err := vpn.dirProvider.GetWireguardDir()
432434
if err != nil {
433435
return "", fmt.Errorf("failed to get wireguard directory: %w", err)
434436
}
435437

436-
// Ensure /etc/wireguard exists with proper permissions
437-
if err := os.MkdirAll(wireguardDir, 0o700); err != nil {
438-
return "", fmt.Errorf("failed to create wireguard directory: %w", err)
439-
}
438+
systemPath := filepath.Join(wireguardDir, serverName+".conf")
440439

441-
// Read source config
442-
configData, err := os.ReadFile(userConfigPath)
443-
if err != nil {
444-
return "", fmt.Errorf("failed to read config: %w", err)
445-
}
440+
// Detect test environment (same logic as GetWireguardDir)
441+
isTestEnv := strings.Contains(wireguardDir, os.TempDir())
446442

447-
// Write to system location
448-
systemPath := filepath.Join(wireguardDir, serverName+".conf")
449-
if err := os.WriteFile(systemPath, configData, 0o600); err != nil {
450-
return "", fmt.Errorf("failed to write system config: %w", err)
443+
if isTestEnv {
444+
// Test environment - use direct file operations
445+
if err := os.MkdirAll(wireguardDir, 0o700); err != nil {
446+
return "", fmt.Errorf("failed to create wireguard directory: %w", err)
447+
}
448+
449+
configData, err := os.ReadFile(userConfigPath)
450+
if err != nil {
451+
return "", fmt.Errorf("failed to read config: %w", err)
452+
}
453+
454+
if err := os.WriteFile(systemPath, configData, 0o600); err != nil {
455+
return "", fmt.Errorf("failed to write system config: %w", err)
456+
}
457+
} else {
458+
// Production environment - use sudo commands
459+
cmd := exec.Command("sudo", "mkdir", "-p", wireguardDir)
460+
if err := cmd.Run(); err != nil {
461+
return "", fmt.Errorf("failed to create wireguard directory: %w", err)
462+
}
463+
464+
cmd = exec.Command("sudo", "chmod", "700", wireguardDir)
465+
if err := cmd.Run(); err != nil {
466+
return "", fmt.Errorf("failed to set directory permissions: %w", err)
467+
}
468+
469+
cmd = exec.Command("sudo", "cp", userConfigPath, systemPath)
470+
if err := cmd.Run(); err != nil {
471+
return "", fmt.Errorf("failed to copy config to system: %w", err)
472+
}
473+
474+
cmd = exec.Command("sudo", "chmod", "600", systemPath)
475+
if err := cmd.Run(); err != nil {
476+
return "", fmt.Errorf("failed to set config file permissions: %w", err)
477+
}
451478
}
452479

453480
return systemPath, nil

0 commit comments

Comments
 (0)