Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add early MFA functionality #188

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

bapung
Copy link

@bapung bapung commented Oct 10, 2022

No description provided.

Comment on lines +21 to +34

# See if we have password and MFA, or just MFA

echo "$pass" | grep -q -i :

if [ $? -eq 0 ];
then
realpass=$(echo "$pass" | cut -d: -f1)
mfatoken=$(echo "$pass" | cut -d: -f2)

# put code here to verify $realpass, the code below the if validates $mfatoken or $pass if false
# exit 0 if the password is correct, the exit below will deny access otherwise
fi

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used at all?


- name: delete clients in db those are not in clients list
set_fact:
cleaned_db: '{{ oath_secrets_db.list | selectattr("username", "in", clients) | list }}'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prefix this with openvpn_mfa_

Comment on lines +38 to +48
- name: prepare list of username and secret to be written to secret file
set_fact:
username_list: '{{ clients_merged | map(attribute="username") | list }}'
secret_list: '{{ clients_merged | map(attribute="secret") | list }}'

- name: write lines to file
copy:
content: "{{ username_list | zip(secret_list) | map('join', ':') | join('\n') }}"
dest: "{{ openvpn_base_dir }}/{{ openvpn_mfa_oathsecrets_file }}"
owner: "{{ openvpn_service_uesr }}"
mode: 0700
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a template that loops over clients_merged instead?

Comment on lines +12 to +20
secret=$(grep -i -m 1 "$user:" {{ openvpn_mfa_oathsecrets_file }} | cut -d: -f2)

# Calculate the code we should expect
code=$(oathtool --totp $secret)

if [ "$code" = "$pass" ];
then
exit 0
fi
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is safe-ish. Only user gets interpolated and that has some character sanitization:

To protect against a client passing a maliciously formed username or password string, the username string must consist only of these characters: alphanumeric, underbar (''), dash ('-'), dot ('.'), or at ('@'). The password string can consist of any printable characters except for CR or LF. Any illegal characters in either the username or password string will be converted to underbar ('').

auth-user-pass-verify in https://openvpn.net/community-resources/reference-manual-for-openvpn-2-0/

I'd much prefer this to be in a script to keep the values as values instead of potentially executing them.

# Calculate the code we should expect
code=$(oathtool --totp $secret)

if [ "$code" = "$pass" ];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$pass should be validated to be all numeric, 6 digits

pass=$(tail -1 $passfile)

# Find the entry in our oath.secrets file, ignore case
secret=$(grep -i -m 1 "$user:" {{ openvpn_mfa_oathsecrets_file }} | cut -d: -f2)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the path have {{ openvpn_base_dir }}/ as a prefix to make it absolute?

Copy link
Owner

@kyl191 kyl191 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general:

  • anything that uses set_fact should have openvpn_mfa_ as a prefix (functionally a namespace)
  • ansible-lint will want fully qualified names
  • the validation script being in bash makes me worry about CLI injection. But other then validating the attacker-controlled secret is actually numeric I don't see another attack route because OpenVPN does character sanitization on the username field. Having it in a script would be preferable but not blocking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants