Skip to content

Commit

Permalink
chore: OpenVPN user and password as nullable
Browse files Browse the repository at this point in the history
- Username and password can be the empty string for custom provider
  • Loading branch information
qdm12 committed Aug 13, 2022
1 parent 8e101d4 commit 1ab74e6
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 46 deletions.
41 changes: 23 additions & 18 deletions internal/configuration/settings/openvpn.go
Expand Up @@ -19,13 +19,15 @@ type OpenVPN struct {
// It can only be "2.4" or "2.5".
Version string
// User is the OpenVPN authentication username.
// It cannot be an empty string in the internal state
// if OpenVPN is used.
User string
// It cannot be nil in the internal state if OpenVPN is used.
// It is usually required but in some cases can be the empty string
// to indicate no user+password authentication is needed.
User *string
// Password is the OpenVPN authentication password.
// It cannot be an empty string in the internal state
// if OpenVPN is used.
Password string
// It cannot be nil in the internal state if OpenVPN is used.
// It is usually required but in some cases can be the empty string
// to indicate no user+password authentication is needed.
Password *string
// ConfFile is a custom OpenVPN configuration file path.
// It can be set to the empty string for it to be ignored.
// It cannot be nil in the internal state.
Expand Down Expand Up @@ -88,14 +90,14 @@ func (o OpenVPN) validate(vpnProvider string) (err error) {

isCustom := vpnProvider == providers.Custom

if !isCustom && o.User == "" {
if !isCustom && *o.User == "" {
return ErrOpenVPNUserIsEmpty
}

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
}

Expand Down Expand Up @@ -204,8 +206,8 @@ func validateOpenVPNClientKey(vpnProvider, clientKey string) (err error) {
func (o *OpenVPN) copy() (copied OpenVPN) {
return OpenVPN{
Version: o.Version,
User: o.User,
Password: o.Password,
User: helpers.CopyStringPtr(o.User),
Password: helpers.CopyStringPtr(o.Password),
ConfFile: helpers.CopyStringPtr(o.ConfFile),
Ciphers: helpers.CopyStringSlice(o.Ciphers),
Auth: helpers.CopyStringPtr(o.Auth),
Expand All @@ -225,8 +227,8 @@ func (o *OpenVPN) copy() (copied OpenVPN) {
// unset field of the receiver settings object.
func (o *OpenVPN) mergeWith(other OpenVPN) {
o.Version = helpers.MergeWithString(o.Version, other.Version)
o.User = helpers.MergeWithString(o.User, other.User)
o.Password = helpers.MergeWithString(o.Password, other.Password)
o.User = helpers.MergeWithStringPtr(o.User, other.User)
o.Password = helpers.MergeWithStringPtr(o.Password, other.Password)
o.ConfFile = helpers.MergeWithStringPtr(o.ConfFile, other.ConfFile)
o.Ciphers = helpers.MergeStringSlices(o.Ciphers, other.Ciphers)
o.Auth = helpers.MergeWithStringPtr(o.Auth, other.Auth)
Expand All @@ -246,8 +248,8 @@ func (o *OpenVPN) mergeWith(other OpenVPN) {
// settings.
func (o *OpenVPN) overrideWith(other OpenVPN) {
o.Version = helpers.OverrideWithString(o.Version, other.Version)
o.User = helpers.OverrideWithString(o.User, other.User)
o.Password = helpers.OverrideWithString(o.Password, other.Password)
o.User = helpers.OverrideWithStringPtr(o.User, other.User)
o.Password = helpers.OverrideWithStringPtr(o.Password, other.Password)
o.ConfFile = helpers.OverrideWithStringPtr(o.ConfFile, other.ConfFile)
o.Ciphers = helpers.OverrideWithStringSlice(o.Ciphers, other.Ciphers)
o.Auth = helpers.OverrideWithStringPtr(o.Auth, other.Auth)
Expand All @@ -264,8 +266,11 @@ func (o *OpenVPN) overrideWith(other OpenVPN) {

func (o *OpenVPN) setDefaults(vpnProvider string) {
o.Version = helpers.DefaultString(o.Version, openvpn.Openvpn25)
o.User = helpers.DefaultStringPtr(o.User, "")
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, "")
Expand Down Expand Up @@ -293,8 +298,8 @@ func (o OpenVPN) String() string {
func (o OpenVPN) toLinesNode() (node *gotree.Node) {
node = gotree.New("OpenVPN settings:")
node.Appendf("OpenVPN version: %s", o.Version)
node.Appendf("User: %s", helpers.ObfuscatePassword(o.User))
node.Appendf("Password: %s", helpers.ObfuscatePassword(o.Password))
node.Appendf("User: %s", helpers.ObfuscatePassword(*o.User))
node.Appendf("Password: %s", helpers.ObfuscatePassword(*o.Password))

if *o.ConfFile != "" {
node.Appendf("Custom configuration file: %s", *o.ConfFile)
Expand Down
21 changes: 16 additions & 5 deletions internal/configuration/sources/env/openvpn.go
Expand Up @@ -72,14 +72,25 @@ func (r *Reader) readOpenVPN() (
return openVPN, nil
}

func (r *Reader) readOpenVPNUser() (user string) {
_, user = r.getEnvWithRetro("OPENVPN_USER", "USER")
func (r *Reader) readOpenVPNUser() (user *string) {
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
return strings.ReplaceAll(user, " ", "")
*user = strings.ReplaceAll(*user, " ", "")
return user
}

func (r *Reader) readOpenVPNPassword() (password string) {
_, password = r.getEnvWithRetro("OPENVPN_PASSWORD", "PASSWORD")
func (r *Reader) readOpenVPNPassword() (password *string) {
password = new(string)
_, *password = r.getEnvWithRetro("OPENVPN_PASSWORD", "PASSWORD")
if *password == "" {
return nil
}

return password
}

Expand Down
15 changes: 0 additions & 15 deletions internal/configuration/sources/secrets/helpers.go
Expand Up @@ -25,18 +25,3 @@ func readSecretFileAsStringPtr(secretPathEnvKey, defaultSecretPath string) (
}
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
}
4 changes: 2 additions & 2 deletions internal/configuration/sources/secrets/openvpn.go
Expand Up @@ -8,15 +8,15 @@ import (

func readOpenVPN() (
settings settings.OpenVPN, err error) {
settings.User, err = readSecretFileAsString(
settings.User, err = readSecretFileAsStringPtr(
"OPENVPN_USER_SECRETFILE",
"/run/secrets/openvpn_user",
)
if err != nil {
return settings, fmt.Errorf("cannot read user file: %w", err)
}

settings.Password, err = readSecretFileAsString(
settings.Password, err = readSecretFileAsStringPtr(
"OPENVPN_PASSWORD_SECRETFILE",
"/run/secrets/openvpn_password",
)
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/custom/openvpnconf.go
Expand Up @@ -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, "auth-retry nointeract")
modified = append(modified, "suppress-timestamps")
if settings.User != "" {
if *settings.User != "" {
modified = append(modified, "auth-user-pass "+openvpn.AuthConf)
}
modified = append(modified, "verb "+strconv.Itoa(*settings.Verbosity))
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/custom/openvpnconf_test.go
Expand Up @@ -36,7 +36,7 @@ func Test_modifyConfig(t *testing.T) {
"auth bla",
},
settings: settings.OpenVPN{
User: "user",
User: stringPtr("user"),
Ciphers: []string{"cipher"},
Auth: stringPtr("auth"),
MSSFix: uint16Ptr(1000),
Expand Down
3 changes: 3 additions & 0 deletions internal/server/helpers.go
@@ -0,0 +1,3 @@
package server

func stringPtr(s string) *string { return &s }
4 changes: 2 additions & 2 deletions internal/server/openvpn.go
Expand Up @@ -94,8 +94,8 @@ func (h *openvpnHandler) setStatus(w http.ResponseWriter, r *http.Request) {
func (h *openvpnHandler) getSettings(w http.ResponseWriter) {
vpnSettings := h.looper.GetSettings()
settings := vpnSettings.OpenVPN
settings.User = "redacted"
settings.Password = "redacted"
settings.User = stringPtr("redacted")
settings.Password = stringPtr("redacted")
encoder := json.NewEncoder(w)
if err := encoder.Encode(settings); err != nil {
h.warner.Warn(err.Error())
Expand Down
4 changes: 2 additions & 2 deletions internal/vpn/openvpn.go
Expand Up @@ -27,8 +27,8 @@ func setupOpenVPN(ctx context.Context, fw Firewall,
return nil, "", fmt.Errorf("failed writing configuration to file: %w", err)
}

if settings.OpenVPN.User != "" {
err := openvpnConf.WriteAuthFile(settings.OpenVPN.User, settings.OpenVPN.Password)
if *settings.OpenVPN.User != "" {
err := openvpnConf.WriteAuthFile(*settings.OpenVPN.User, *settings.OpenVPN.Password)
if err != nil {
return nil, "", fmt.Errorf("failed writing auth to file: %w", err)
}
Expand Down

0 comments on commit 1ab74e6

Please sign in to comment.