chore: OpenVPN user and password as nullable

- Username and password can be the empty string for custom provider
This commit is contained in:
Quentin McGaw
2022-08-13 16:44:38 +00:00
parent 8e101d49a1
commit 1ab74e6bb3
9 changed files with 50 additions and 46 deletions

View File

@@ -19,13 +19,15 @@ type OpenVPN struct {
// It can only be "2.4" or "2.5". // It can only be "2.4" or "2.5".
Version string Version string
// User is the OpenVPN authentication username. // User is the OpenVPN authentication username.
// It cannot be an empty string in the internal state // It cannot be nil in the internal state if OpenVPN is used.
// if OpenVPN is used. // It is usually required but in some cases can be the empty string
User string // to indicate no user+password authentication is needed.
User *string
// Password is the OpenVPN authentication password. // Password is the OpenVPN authentication password.
// It cannot be an empty string in the internal state // It cannot be nil in the internal state if OpenVPN is used.
// if OpenVPN is used. // It is usually required but in some cases can be the empty string
Password string // to indicate no user+password authentication is needed.
Password *string
// ConfFile is a custom OpenVPN configuration file path. // ConfFile is a custom OpenVPN configuration file path.
// It can be set to the empty string for it to be ignored. // It can be set to the empty string for it to be ignored.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
@@ -88,14 +90,14 @@ func (o OpenVPN) validate(vpnProvider string) (err error) {
isCustom := vpnProvider == providers.Custom isCustom := vpnProvider == providers.Custom
if !isCustom && o.User == "" { if !isCustom && *o.User == "" {
return ErrOpenVPNUserIsEmpty return ErrOpenVPNUserIsEmpty
} }
passwordRequired := !isCustom && passwordRequired := !isCustom &&
(vpnProvider != providers.Ivpn || !ivpnAccountID.MatchString(o.User)) (vpnProvider != providers.Ivpn || !ivpnAccountID.MatchString(*o.User))
if passwordRequired && o.Password == "" { if passwordRequired && *o.Password == "" {
return ErrOpenVPNPasswordIsEmpty return ErrOpenVPNPasswordIsEmpty
} }
@@ -204,8 +206,8 @@ func validateOpenVPNClientKey(vpnProvider, clientKey string) (err error) {
func (o *OpenVPN) copy() (copied OpenVPN) { func (o *OpenVPN) copy() (copied OpenVPN) {
return OpenVPN{ return OpenVPN{
Version: o.Version, Version: o.Version,
User: o.User, User: helpers.CopyStringPtr(o.User),
Password: o.Password, Password: helpers.CopyStringPtr(o.Password),
ConfFile: helpers.CopyStringPtr(o.ConfFile), ConfFile: helpers.CopyStringPtr(o.ConfFile),
Ciphers: helpers.CopyStringSlice(o.Ciphers), Ciphers: helpers.CopyStringSlice(o.Ciphers),
Auth: helpers.CopyStringPtr(o.Auth), Auth: helpers.CopyStringPtr(o.Auth),
@@ -225,8 +227,8 @@ func (o *OpenVPN) copy() (copied OpenVPN) {
// unset field of the receiver settings object. // unset field of the receiver settings object.
func (o *OpenVPN) mergeWith(other OpenVPN) { func (o *OpenVPN) mergeWith(other OpenVPN) {
o.Version = helpers.MergeWithString(o.Version, other.Version) o.Version = helpers.MergeWithString(o.Version, other.Version)
o.User = helpers.MergeWithString(o.User, other.User) o.User = helpers.MergeWithStringPtr(o.User, other.User)
o.Password = helpers.MergeWithString(o.Password, other.Password) o.Password = helpers.MergeWithStringPtr(o.Password, other.Password)
o.ConfFile = helpers.MergeWithStringPtr(o.ConfFile, other.ConfFile) o.ConfFile = helpers.MergeWithStringPtr(o.ConfFile, other.ConfFile)
o.Ciphers = helpers.MergeStringSlices(o.Ciphers, other.Ciphers) o.Ciphers = helpers.MergeStringSlices(o.Ciphers, other.Ciphers)
o.Auth = helpers.MergeWithStringPtr(o.Auth, other.Auth) o.Auth = helpers.MergeWithStringPtr(o.Auth, other.Auth)
@@ -246,8 +248,8 @@ func (o *OpenVPN) mergeWith(other OpenVPN) {
// settings. // settings.
func (o *OpenVPN) overrideWith(other OpenVPN) { func (o *OpenVPN) overrideWith(other OpenVPN) {
o.Version = helpers.OverrideWithString(o.Version, other.Version) o.Version = helpers.OverrideWithString(o.Version, other.Version)
o.User = helpers.OverrideWithString(o.User, other.User) o.User = helpers.OverrideWithStringPtr(o.User, other.User)
o.Password = helpers.OverrideWithString(o.Password, other.Password) o.Password = helpers.OverrideWithStringPtr(o.Password, other.Password)
o.ConfFile = helpers.OverrideWithStringPtr(o.ConfFile, other.ConfFile) o.ConfFile = helpers.OverrideWithStringPtr(o.ConfFile, other.ConfFile)
o.Ciphers = helpers.OverrideWithStringSlice(o.Ciphers, other.Ciphers) o.Ciphers = helpers.OverrideWithStringSlice(o.Ciphers, other.Ciphers)
o.Auth = helpers.OverrideWithStringPtr(o.Auth, other.Auth) o.Auth = helpers.OverrideWithStringPtr(o.Auth, other.Auth)
@@ -264,8 +266,11 @@ func (o *OpenVPN) overrideWith(other OpenVPN) {
func (o *OpenVPN) setDefaults(vpnProvider string) { func (o *OpenVPN) setDefaults(vpnProvider string) {
o.Version = helpers.DefaultString(o.Version, openvpn.Openvpn25) o.Version = helpers.DefaultString(o.Version, openvpn.Openvpn25)
o.User = helpers.DefaultStringPtr(o.User, "")
if vpnProvider == providers.Mullvad { if vpnProvider == providers.Mullvad {
o.Password = "m" o.Password = helpers.DefaultStringPtr(o.Password, "m")
} else {
o.Password = helpers.DefaultStringPtr(o.Password, "")
} }
o.ConfFile = helpers.DefaultStringPtr(o.ConfFile, "") o.ConfFile = helpers.DefaultStringPtr(o.ConfFile, "")
@@ -293,8 +298,8 @@ func (o OpenVPN) String() string {
func (o OpenVPN) toLinesNode() (node *gotree.Node) { func (o OpenVPN) toLinesNode() (node *gotree.Node) {
node = gotree.New("OpenVPN settings:") node = gotree.New("OpenVPN settings:")
node.Appendf("OpenVPN version: %s", o.Version) node.Appendf("OpenVPN version: %s", o.Version)
node.Appendf("User: %s", helpers.ObfuscatePassword(o.User)) node.Appendf("User: %s", helpers.ObfuscatePassword(*o.User))
node.Appendf("Password: %s", helpers.ObfuscatePassword(o.Password)) node.Appendf("Password: %s", helpers.ObfuscatePassword(*o.Password))
if *o.ConfFile != "" { if *o.ConfFile != "" {
node.Appendf("Custom configuration file: %s", *o.ConfFile) node.Appendf("Custom configuration file: %s", *o.ConfFile)

View File

@@ -72,14 +72,25 @@ func (r *Reader) readOpenVPN() (
return openVPN, nil return openVPN, nil
} }
func (r *Reader) readOpenVPNUser() (user string) { func (r *Reader) readOpenVPNUser() (user *string) {
_, user = r.getEnvWithRetro("OPENVPN_USER", "USER") user = new(string)
_, *user = r.getEnvWithRetro("OPENVPN_USER", "USER")
if *user == "" {
return nil
}
// Remove spaces in user ID to simplify user's life, thanks @JeordyR // Remove spaces in user ID to simplify user's life, thanks @JeordyR
return strings.ReplaceAll(user, " ", "") *user = strings.ReplaceAll(*user, " ", "")
return user
} }
func (r *Reader) readOpenVPNPassword() (password string) { func (r *Reader) readOpenVPNPassword() (password *string) {
_, password = r.getEnvWithRetro("OPENVPN_PASSWORD", "PASSWORD") password = new(string)
_, *password = r.getEnvWithRetro("OPENVPN_PASSWORD", "PASSWORD")
if *password == "" {
return nil
}
return password return password
} }

View File

@@ -25,18 +25,3 @@ func readSecretFileAsStringPtr(secretPathEnvKey, defaultSecretPath string) (
} }
return files.ReadFromFile(path) return files.ReadFromFile(path)
} }
func readSecretFileAsString(secretPathEnvKey, defaultSecretPath string) (
s string, err error) {
path := getCleanedEnv(secretPathEnvKey)
if path == "" {
path = defaultSecretPath
}
stringPtr, err := files.ReadFromFile(path)
if err != nil {
return "", err
} else if stringPtr == nil {
return "", nil
}
return *stringPtr, nil
}

View File

@@ -8,7 +8,7 @@ import (
func readOpenVPN() ( func readOpenVPN() (
settings settings.OpenVPN, err error) { settings settings.OpenVPN, err error) {
settings.User, err = readSecretFileAsString( settings.User, err = readSecretFileAsStringPtr(
"OPENVPN_USER_SECRETFILE", "OPENVPN_USER_SECRETFILE",
"/run/secrets/openvpn_user", "/run/secrets/openvpn_user",
) )
@@ -16,7 +16,7 @@ func readOpenVPN() (
return settings, fmt.Errorf("cannot read user file: %w", err) return settings, fmt.Errorf("cannot read user file: %w", err)
} }
settings.Password, err = readSecretFileAsString( settings.Password, err = readSecretFileAsStringPtr(
"OPENVPN_PASSWORD_SECRETFILE", "OPENVPN_PASSWORD_SECRETFILE",
"/run/secrets/openvpn_password", "/run/secrets/openvpn_password",
) )

View File

@@ -74,7 +74,7 @@ func modifyConfig(lines []string, connection models.Connection,
modified = append(modified, "pull-filter ignore \"auth-token\"") // prevent auth failed loop modified = append(modified, "pull-filter ignore \"auth-token\"") // prevent auth failed loop
modified = append(modified, "auth-retry nointeract") modified = append(modified, "auth-retry nointeract")
modified = append(modified, "suppress-timestamps") modified = append(modified, "suppress-timestamps")
if settings.User != "" { if *settings.User != "" {
modified = append(modified, "auth-user-pass "+openvpn.AuthConf) modified = append(modified, "auth-user-pass "+openvpn.AuthConf)
} }
modified = append(modified, "verb "+strconv.Itoa(*settings.Verbosity)) modified = append(modified, "verb "+strconv.Itoa(*settings.Verbosity))

View File

@@ -36,7 +36,7 @@ func Test_modifyConfig(t *testing.T) {
"auth bla", "auth bla",
}, },
settings: settings.OpenVPN{ settings: settings.OpenVPN{
User: "user", User: stringPtr("user"),
Ciphers: []string{"cipher"}, Ciphers: []string{"cipher"},
Auth: stringPtr("auth"), Auth: stringPtr("auth"),
MSSFix: uint16Ptr(1000), MSSFix: uint16Ptr(1000),

View File

@@ -0,0 +1,3 @@
package server
func stringPtr(s string) *string { return &s }

View File

@@ -94,8 +94,8 @@ func (h *openvpnHandler) setStatus(w http.ResponseWriter, r *http.Request) {
func (h *openvpnHandler) getSettings(w http.ResponseWriter) { func (h *openvpnHandler) getSettings(w http.ResponseWriter) {
vpnSettings := h.looper.GetSettings() vpnSettings := h.looper.GetSettings()
settings := vpnSettings.OpenVPN settings := vpnSettings.OpenVPN
settings.User = "redacted" settings.User = stringPtr("redacted")
settings.Password = "redacted" settings.Password = stringPtr("redacted")
encoder := json.NewEncoder(w) encoder := json.NewEncoder(w)
if err := encoder.Encode(settings); err != nil { if err := encoder.Encode(settings); err != nil {
h.warner.Warn(err.Error()) h.warner.Warn(err.Error())

View File

@@ -27,8 +27,8 @@ func setupOpenVPN(ctx context.Context, fw Firewall,
return nil, "", fmt.Errorf("failed writing configuration to file: %w", err) return nil, "", fmt.Errorf("failed writing configuration to file: %w", err)
} }
if settings.OpenVPN.User != "" { if *settings.OpenVPN.User != "" {
err := openvpnConf.WriteAuthFile(settings.OpenVPN.User, settings.OpenVPN.Password) err := openvpnConf.WriteAuthFile(*settings.OpenVPN.User, *settings.OpenVPN.Password)
if err != nil { if err != nil {
return nil, "", fmt.Errorf("failed writing auth to file: %w", err) return nil, "", fmt.Errorf("failed writing auth to file: %w", err)
} }