When a client announces its support to support text based
challenge/response via IV_SOO=cr_text,the client needs to also
be able to reply to that response.
This adds the "cr-response" management function to be able to
do this. The answer should be base64 encoded.
Signed-off-by: Arne Schwabe
---
doc/management-notes.txt | 8
src/openvpn/init.c | 39 +++
src/openvpn/manage.c | 39 ++-
src/openvpn/manage.h | 1 +
4 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/doc/management-notes.txt b/doc/management-notes.txt
index 17645c1d..e380ca2b 100644
--- a/doc/management-notes.txt
+++ b/doc/management-notes.txt
@@ -806,6 +806,14 @@ To accept connecting to the host and port directly, use
this command:
proxy NONE
+COMMAND -- cr-response (OpenVPN 2.5 or higher)
+-
+Provides support for sending responses a challenge/response
+query via INFOMSG,CR_TEXT. The response should be base64 encoded:
+
+ cr-response SGFsbG8gV2VsdCE=
+
+
COMMAND -- pk-sig (OpenVPN 2.5 or higher, management version > 1)
COMMAND -- rsa-sig (OpenVPN 2.3 or higher, management version <= 1)
-
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 0bdb0a9c..77c1c23b 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -288,6 +288,44 @@ ce_management_query_proxy(struct context *c)
return ret;
}
+/**
+ * This method sends a custom control channel message
+ *
+ * This will write the control message
+ *
+ * command parm1,parm2,..
+ * .
+ * to the control channel.
+ *
+ * @param arg The context struct
+ * @param command The command being sent
+ * @param parametersthe parameters to the command
+ * @return if sending was successful
+ */
+static bool
+management_callback_send_cc_mesage(void *arg,
+ const char *command,
+ const char *parameters)
+{
+struct context *c = (struct context *) arg;
+size_t len = strlen(command) + 1 + sizeof(parameters) + 1;
+if (len > PUSH_BUNDLE_SIZE)
+{
+return false;
+}
+
+struct gc_arena gc = gc_new();
+struct buffer buf = alloc_buf_gc(len, &gc);
+ASSERT(buf_printf(&buf, "%s", command));
+if (parameters)
+{
+ASSERT(buf_printf(&buf, ",%s", parameters));
+}
+bool status = send_control_channel_string(c, BSTR(&buf), D_PUSH);
+
+gc_free(&gc);
+return status;
+}
static bool
management_callback_remote_cmd(void *arg, const char **p)
@@ -3990,6 +4028,7 @@ init_management_callback_p2p(struct context *c)
cb.show_net = management_show_net_callback;
cb.proxy_cmd = management_callback_proxy_cmd;
cb.remote_cmd = management_callback_remote_cmd;
+cb.send_cc_message = management_callback_send_cc_mesage;
#ifdef TARGET_ANDROID
cb.network_change = management_callback_network_change;
#endif
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 1d97c2b6..8dada6f2 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -75,6 +75,7 @@ man_help(void)
msg(M_CLIENT, "auth-retry t : Auth failure retry mode
(none,interact,nointeract).");
msg(M_CLIENT, "bytecount n: Show bytes in/out, update every n
secs (0=off).");
msg(M_CLIENT, "echo [on|off] [N|all] : Like log, but only show messages
in echo buffer.");
+msg(M_CLIENT, "cr-response response : Send a challenge response answer
via CR_RESPONSE to server");
msg(M_CLIENT, "exit|quit : Close management session.");
msg(M_CLIENT, "forget-passwords : Forget passwords entered so far.");
msg(M_CLIENT, "help : Print this message.");
@@ -779,6 +780,27 @@ man_net(struct management *man)
}
}
+static void
+man_send_cc_message(struct management *man, const char *message, const char
*parameters)
+{
+if (man->persist.callback.send_cc_message)
+{
+const bool status = (*man->persist.callback.send_cc_message)
+(man->persist.callback.arg, message, parameters);
+if (status)
+{
+msg(M_CLIENT, "SUCCESS: command succeeded");
+}
+else
+{
+msg(M_CLIENT, "ERROR: command failed");
+}
+}
+else
+{
+msg(M_CLIENT, "ERROR: This command is not supported by the current
daemon mode");
+}
+}
#ifdef ENABLE_PKCS11
static void
@@ -1144,7 +1166,15 @@ man_load_stats(struct management *man)
}
#define MN_AT_LEAST (1<<0)
-
+/**
+ * Checks if the correct number of arguments to a management command are
present
+ * and otherwise prints an error and returns false.
+ *
+ * @param p pointer to the parameter array
+ * @param n number of arguments required
+ * @param flags