@@ -39,6 +39,29 @@
* seconds after the initial TLS negotiation, using
* {common-name}.pf as the source.
*
+ * Additional web based authentication is also partly
+ * demonstrated if adding these two lines:
+ *
+ * setenv test_deferred_openurl https://auth.example.org/
+ * setenv test_deferred_timeout 30
+ *
+ * This will NOT do any real authentication, but will send
+ * the URL to the client which can open the authentication
+ * page. If the test_deferred_timeout is higher than
+ * test_deferred_auth, the authentication will pass (regardless
+ * of username/password provided and what ever happens on the
+ * authentication URL). If the test_deferred_timeout is lower
+ * than test_deferred_auth, the authentication will fail.
+ * For the fail or pass to work properly make sure there are
+ * at least 10-15 seconds difference between test_deferred_auth
+ * and test_deferred_timeout.
+ *
+ * This kind of additional web authentication can be useful
+ * in real life scenarios for various types of 2FA methods
+ * triggered via web; or to open a page with disclaimers and
+ * terms of service needed to be accepted before getting a
+ * connection.
+ *
* Sample packet filter configuration:
*
* [CLIENTS DROP]
@@ -72,6 +95,8 @@ static plugin_log_t plugin_log = NULL;
struct plugin_context {
int test_deferred_auth;
int test_packet_filter;
+ int test_deferred_timeout;
+ char *test_deferred_openurl;
};
struct plugin_per_client_context {
@@ -169,6 +194,23 @@ openvpn_plugin_open_v3(const int v3structver,
context->test_deferred_auth = atoi_null0(get_env("test_deferred_auth", envp));
plugin_log(PLOG_NOTE, MODULE, "TEST_DEFERRED_AUTH %d", context->test_deferred_auth);
+ context->test_deferred_timeout = atoi_null0(get_env("test_deferred_timeout", envp));
+ plugin_log(PLOG_NOTE, MODULE, "TEST_DEFERRED_TIMEOUT %d", context->test_deferred_timeout);
+
+ const char *openurl = get_env("test_deferred_openurl", envp);
+ if (openurl)
+ {
+ if (context->test_deferred_timeout < 1)
+ {
+ plugin_log(PLOG_ERR, MODULE, "test_deferred_timeout also requires test_deferred_openurl");
+ goto error;
+ }
+ size_t len = strlen(openurl);
+ context->test_deferred_openurl = calloc(1, len+1);
+ strncpy(context->test_deferred_openurl, openurl, len);
+ plugin_log(PLOG_NOTE, MODULE, "TEST_DEFERRED_OPENURL %s", openurl);
+ }
+
context->test_packet_filter = atoi_null0(get_env("test_packet_filter", envp));
plugin_log(PLOG_NOTE, MODULE, "TEST_PACKET_FILTER %d", context->test_packet_filter);
@@ -222,11 +264,13 @@ auth_user_pass_verify(struct plugin_context *context,
/* get auth_control_file filename from envp string array*/
const char *auth_control_file = get_env("auth_control_file", envp);
+ const char *auth_pending_file = get_env("auth_pending_file", envp);
- plugin_log(PLOG_NOTE, MODULE, "DEFER u='%s' p='%s' acf='%s'",
+ plugin_log(PLOG_NOTE, MODULE, "DEFER u='%s' p='%s' acf='%s' apf='%s'",
np(username),
np(password),
- np(auth_control_file));
+ np(auth_control_file),
+ np(auth_pending_file));
/* Authenticate asynchronously in n seconds */
if (!auth_control_file)
@@ -234,6 +278,32 @@ auth_user_pass_verify(struct plugin_context *context,
return OPENVPN_PLUGIN_FUNC_ERROR;
}
+ if (auth_pending_file && context->test_deferred_openurl)
+ {
+ /*
+ * This will make OpenVPN clients capable of web authentication open the
+ * the provided URL - but this plug-in does not provide any side-channel
+ * authentication services. This is purely for demonstration how to
+ * make a client open an URL for authentication, NOT the web authentication
+ * impelementation itself.
+ *
+ * Remember, this plug-in will NOT do any real authentication. Any
+ * username/password is considered valid. It only demonstrates various
+ * deferred authentication mechanisms.
+ *
+ */
+ FILE *pfd = fopen(auth_pending_file, "w");
+ if (!pfd)
+ {
+ plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "auth_pending_file open('%s') failed", auth_pending_file);
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+ fprintf(pfd, "%d\n", context->test_deferred_timeout);
+ fprintf(pfd, "openurl\n");
+ fprintf(pfd, "OPEN_URL:%s\n", context->test_deferred_openurl);
+ fclose(pfd);
+ }
+
/* we do not want to complicate our lives with having to wait()
* for child processes (so they are not zombiefied) *and* we MUST NOT
* fiddle with signal handlers (= shared with openvpn main), so
@@ -513,5 +583,9 @@ openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
{
struct plugin_context *context = (struct plugin_context *) handle;
plugin_log(PLOG_NOTE, MODULE, "FUNC: openvpn_plugin_close_v1");
+ if (context->test_deferred_openurl)
+ {
+ free(context->test_deferred_openurl);
+ }
free(context);
}