Hi, Thanks for the feedback.
I should have made it clear that this was a request for comment about the concept. Whilst the functionality works for the setup I've tested with, I've not reviewed cases of admin or auth-user-pass-verify scripts so there are potential gaps I'll need to go back and fill. For background, the options are based on Linux PAM: https://linux.die.net/man/5/pam.conf. I don't use all the PAM configuration in any of my set-ups, but I know of people who cover use-cases through the likes of Optional, so didn't want to exclude it unless there's a strong consensus that it wouldn't provide value in the OpenVPN case. > This seems to only if you are using a different MFA approach than the > current/recommended one, e.g. demonstrated by the demo script totp.py in > the OpenVPN repository. > This is primarily aimed at out-of-band Push OTP rather than a user entering a TOTP into their VPN client. > To better understand what this patch is actually addressing, it would be > nice to describe the scenario that you are addressing with this patch as > that me do better understand what real-world scenario is actually > addressed by this patch as the this is a bit abstract. > > The use case I'm working with is LDAP authentication followed by a Duo Push, with the requirement being not to perform a Duo Push unless LDAP succeeds. Both of these are initiated from server-side plugins, which I don't think the TOTP script handles, but I'm happy to be told there's an easy way of doing this! > plugin foo foo > > could be both as > > plugin module-name "arguments" > > and as > > plugin [scope] module-name > > > according to the man page. I do not like the approach of using a > whitelist of argument to determine which of the two is being used as a > typo for example or using an old version can then change the parsing in > unexpected way. I would rather see something that has not this ambiguity > like introducing a new keyword like plugin-something. > > > There would only be an incompatibility between old and new versions if you had a binary named `optional`, `required`, `requisite`, or `suffiicient` on your path, and at that point your OpenVPN is likely to fail on the Plugin Init phase as the binary won't have the expected init methods in it, otherwise you'd get an error about not finding the binary for plugin `required`. Similarly having a typo in the configuration would result in OpenVPN failing to start with a message about being unable to find the target binary for the plugin `reequired`. I did consider adding a new `scoped-plugin` item, but wanted to avoid the ambiguity of someone mixing 'auth' plugins in `plugin` and `scoped-plugin`, or using plugins that don't support scope (i.e. non-auth plugins) in `scoped-plugin`. Do you have any suggestions about how you'd differentiate existing plugins and the new plugin type to prevent ambiguity from mix-and-matching old-and-new configuration, e.g. adding two auth-pam entries, one under an existing `plugin` line and one under the newly named `scoped-plugin` line? > What happens with other auth methods like management and auth scripts? > That should be made clear without having to read the source code. > I've not looked at these yet. I'll come back to you on the actual implementation of these. > > What happens if all plugins are optinal. And what is the point of a > plugin being called but ignored? Some idea what to use this for would be > good. > > Good point. Just now OpenVPN terminates if verify-client-cert is `none` and then doesn't have any auth-user-pass-verify scripts or plugins, but this change doesn't prevent someone setting only `sufficient` plugins that all fail, or only setting `optional` plugins. I can harden this by performing a configuration check to ensure a non-optional plugin is set after loading all plugins and to ensure there's no fall-through for all 'sufficient' plugins failing. I don't use Optional in any of the PAM configurations I have, but know the common use-case is for ensuring keyrings/keychains are unlocked but not failing if they're unavailable. > > + > > + If :code:`scope` is not specified for an auth plugin then the plugin > will > > + be treated as :code:`required`. > > do we define what an auth plugin vs a non-plugin is anywhere? > No. This is a terminology I've gone with rather than an OpenVPN nomenclature. It's any plugin that returns the OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY mask but didn't have a meaningful name for it that didn't refer to a constant in the code. I'm happy to take any suggestions on how to better define that category of plugins. > > > + If :code:`scope` is specified for a non-auth plugin then the > configuration > > + will be treated as invalid. > > + > > And then what will happen? > OpenVPN will exit with an error about the configuration being invalid. Are you wanting this to be explicitly called-out? > > +static char * > > +plugin_scope_name(enum plugin_scope scope) > > +{ > > + switch (scope) > > + { > > + case PLUGIN_SCOPE_REQUIRED: > > + return "required"; > > + > > + case PLUGIN_SCOPE_REQUISITE: > > + return "requisite"; > > + > > + case PLUGIN_SCOPE_SUFFICIENT: > > + return "sufficient"; > > + > > + case PLUGIN_SCOPE_OPTIONAL: > > + return "optional"; > > + > > + default: > > + return ""; > > + } > The PLUGIN_SCOPE_UNDEFINED is missing from this function and default > should be something other than an empty string I think > > This was intentional - the only way you can have UNDEFINED is not to have defined a scope so when printing it back out anywhere I wanted to show the same value as what the user had originally entered. > > > > > + bool non_scope_sufficient_auth_plugin_seen = false; > > I have trouble parsing this variable name and meaning. A plugin without > scope is required from the earlier manpage changes. The combination of > no scope but a sufficent scope makes no sense to me. > Agreed the naming isn't great here. This is enforcing the section from the manpage about ":code:`sufficient` plugins must be listed before any other plugins.", so checking if we've seen something that's not a `sufficient` plugin as we iterate over plugins. However, re-reading the PAM config man page the 'sufficient' should be able to be placed anywhere but have the result ignore if a previous 'required' or 'requisite' plugin has failed. I'll do some refactoring to make this work as-per what PAM is doing which will ultimately remove the block of code in this area. > > + msg(M_FATAL, > > + "PLUGIN_INIT: auth plugin %s is defined as > 'sufficient' but has been specified after other auth plugins not specified > as 'sufficient'", > > + pc->plugins[i].so_pathname); > > + } > > Is this restriction documented in the man page? Also why has this > decision been made. I don't see any obvious reason for it. > > Yes: " :code:`sufficient` plugins must be listed before any other plugins.". This was to prevent ambiguity with a requisite or required plugin failing and having a sufficient plugin listed afterwards. As mentioned above I've misunderstood what PAM does in this area, so will update my implementation to be less restrictive. Thanks, Michael
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel