summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Yonan <james@openvpn.net>2011-07-05 00:33:55 +0000
committerJames Yonan <james@openvpn.net>2011-07-05 00:33:55 +0000
commit54561af63699e7408fba11c75bbf9e22ed6216dc (patch)
treef75b352719fab8367306b383a18fc6779beeae7c
parent5cdb5e0111df7b3d4da7e28390af6e4f26b2cdbe (diff)
downloadopenvpn-54561af63699e7408fba11c75bbf9e22ed6216dc.tar.gz
openvpn-54561af63699e7408fba11c75bbf9e22ed6216dc.tar.xz
openvpn-54561af63699e7408fba11c75bbf9e22ed6216dc.zip
Added "management-query-remote" directive (client) to allow
the management interface to override the "remote" directive. See "remote" command in management/management-notes.txt for documentation. Version 2.1.4. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7410 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--init.c116
-rw-r--r--manage.c41
-rw-r--r--manage.h16
-rw-r--r--management/management-notes.txt32
-rw-r--r--openvpn.86
-rw-r--r--options.c10
-rw-r--r--options.h22
-rw-r--r--syshead.h9
-rw-r--r--version.m42
9 files changed, 242 insertions, 12 deletions
diff --git a/init.c b/init.c
index b3613b7..0e567e6 100644
--- a/init.c
+++ b/init.c
@@ -199,6 +199,90 @@ management_callback_http_proxy_fallback_cmd (void *arg, const char *server, cons
#endif
+#if MANAGEMENT_QUERY_REMOTE
+
+static bool
+management_callback_remote_cmd (void *arg, const char **p)
+{
+ struct context *c = (struct context *) arg;
+ struct connection_entry *ce = &c->options.ce;
+ int ret = false;
+ if (p[1] && ((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT)&CE_MAN_QUERY_REMOTE_MASK) == CE_MAN_QUERY_REMOTE_QUERY)
+ {
+ int flags = 0;
+ if (!strcmp(p[1], "ACCEPT"))
+ {
+ flags = CE_MAN_QUERY_REMOTE_ACCEPT;
+ ret = true;
+ }
+ else if (!strcmp(p[1], "SKIP"))
+ {
+ flags = CE_MAN_QUERY_REMOTE_SKIP;
+ ret = true;
+ }
+ else if (!strcmp(p[1], "MOD") && p[2] && p[3])
+ {
+ const int port = atoi(p[3]);
+ if (strlen(p[2]) < RH_HOST_LEN && legal_ipv4_port(port))
+ {
+ struct remote_host_store *rhs = c->options.rh_store;
+ if (!rhs)
+ {
+ ALLOC_OBJ_CLEAR_GC (rhs, struct remote_host_store, &c->options.gc);
+ c->options.rh_store = rhs;
+ }
+ strncpynt(rhs->host, p[2], RH_HOST_LEN);
+ ce->remote = rhs->host;
+ ce->remote_port = port;
+ flags = CE_MAN_QUERY_REMOTE_MOD;
+ ret = true;
+ }
+ }
+ if (ret)
+ {
+ ce->flags &= ~(CE_MAN_QUERY_REMOTE_MASK<<CE_MAN_QUERY_REMOTE_SHIFT);
+ ce->flags |= ((flags&CE_MAN_QUERY_REMOTE_MASK)<<CE_MAN_QUERY_REMOTE_SHIFT);
+ }
+ }
+ return ret;
+}
+
+static bool
+ce_management_query_remote (struct context *c, const char *remote_ip_hint)
+{
+ struct gc_arena gc = gc_new ();
+ volatile struct connection_entry *ce = &c->options.ce;
+ int ret = true;
+ update_time();
+ if (management)
+ {
+ struct buffer out = alloc_buf_gc (256, &gc);
+ buf_printf (&out, ">REMOTE:%s,%d,%s", np(ce->remote), ce->remote_port, proto2ascii(ce->proto, false));
+ management_notify_generic(management, BSTR (&out));
+ ce->flags &= ~(CE_MAN_QUERY_REMOTE_MASK<<CE_MAN_QUERY_REMOTE_SHIFT);
+ ce->flags |= (CE_MAN_QUERY_REMOTE_QUERY<<CE_MAN_QUERY_REMOTE_SHIFT);
+ while (((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT) & CE_MAN_QUERY_REMOTE_MASK) == CE_MAN_QUERY_REMOTE_QUERY)
+ {
+ management_event_loop_n_seconds (management, 1);
+ if (IS_SIG (c))
+ {
+ ret = false;
+ break;
+ }
+ }
+ }
+ {
+ const int flags = ((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT) & CE_MAN_QUERY_REMOTE_MASK);
+ if (flags == CE_MAN_QUERY_REMOTE_ACCEPT && remote_ip_hint)
+ ce->remote = remote_ip_hint;
+ ret = (flags != CE_MAN_QUERY_REMOTE_SKIP);
+ }
+ gc_free (&gc);
+ return ret;
+}
+
+#endif
+
/*
* Initialize and possibly randomize connection list.
*/
@@ -313,6 +397,15 @@ next_connection_entry (struct context *c)
c->options.ce = *ce;
+#if MANAGEMENT_QUERY_REMOTE
+ if (ce_defined && management && management_query_remote_enabled(management))
+ {
+ /* allow management interface to override connection entry details */
+ ce_defined = ce_management_query_remote(c, remote_ip_hint);
+ if (IS_SIG (c))
+ break;
+ } else
+#endif
if (remote_ip_hint)
c->options.ce.remote = remote_ip_hint;
@@ -2975,6 +3068,9 @@ init_management_callback_p2p (struct context *c)
#if HTTP_PROXY_FALLBACK
cb.http_proxy_fallback_cmd = management_callback_http_proxy_fallback_cmd;
#endif
+#if MANAGEMENT_QUERY_REMOTE
+ cb.remote_cmd = management_callback_remote_cmd;
+#endif
management_set_callback (management, &cb);
}
#endif
@@ -3110,6 +3206,16 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
goto sig;
}
+ /* should we disable paging? */
+ if (c->first_time && options->mlock)
+ do_mlockall (true);
+
+#if P2MP
+ /* get passwords if undefined */
+ if (auth_retry_get () == AR_INTERACT)
+ init_query_passwords (c);
+#endif
+
/* map in current connection entry */
next_connection_entry (c);
@@ -3124,16 +3230,6 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
link_socket_mode = LS_MODE_TCP_ACCEPT_FROM;
}
- /* should we disable paging? */
- if (c->first_time && options->mlock)
- do_mlockall (true);
-
-#if P2MP
- /* get passwords if undefined */
- if (auth_retry_get () == AR_INTERACT)
- init_query_passwords (c);
-#endif
-
/* initialize context level 2 --verb/--mute parms */
init_verb_mute (c, IVM_LEVEL_2);
diff --git a/manage.c b/manage.c
index 439bd76..df58ce4 100644
--- a/manage.c
+++ b/manage.c
@@ -86,6 +86,9 @@ man_help ()
msg (M_CLIENT, " where action is reply string.");
msg (M_CLIENT, "net : (Windows only) Show network info and routing table.");
msg (M_CLIENT, "password type p : Enter password p for a queried OpenVPN password.");
+#if MANAGEMENT_QUERY_REMOTE
+ msg (M_CLIENT, "remote type [host port] : Override remote directive, type=ACCEPT|MOD|SKIP.");
+#endif
msg (M_CLIENT, "pid : Show process ID of the current OpenVPN process.");
#ifdef ENABLE_PKCS11
msg (M_CLIENT, "pkcs11-id-count : Get number of available PKCS#11 identities.");
@@ -1085,6 +1088,31 @@ man_http_proxy_fallback (struct management *man, const char *server, const char
#endif
+#if MANAGEMENT_QUERY_REMOTE
+
+static void
+man_remote (struct management *man, const char **p)
+{
+ if (man->persist.callback.remote_cmd)
+ {
+ const bool status = (*man->persist.callback.remote_cmd)(man->persist.callback.arg, p);
+ if (status)
+ {
+ msg (M_CLIENT, "SUCCESS: remote command succeeded");
+ }
+ else
+ {
+ msg (M_CLIENT, "ERROR: remote command failed");
+ }
+ }
+ else
+ {
+ msg (M_CLIENT, "ERROR: The remote command is not supported by the current daemon mode");
+ }
+}
+
+#endif
+
static void
man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms)
{
@@ -1314,6 +1342,13 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
man_http_proxy_fallback (man, NULL, NULL, NULL);
}
#endif
+#if MANAGEMENT_QUERY_REMOTE
+ else if (streq (p[0], "remote"))
+ {
+ if (man_need (man, p, 1, MN_AT_LEAST))
+ man_remote (man, p);
+ }
+#endif
#if 1
else if (streq (p[0], "test"))
{
@@ -2334,6 +2369,12 @@ management_notify(struct management *man, const char *severity, const char *type
msg (M_CLIENT, ">NOTIFY:%s,%s,%s", severity, type, text);
}
+void
+management_notify_generic (struct management *man, const char *str)
+{
+ msg (M_CLIENT, "%s", str);
+}
+
#ifdef MANAGEMENT_DEF_AUTH
static bool
diff --git a/manage.h b/manage.h
index 288e47b..f681f8d 100644
--- a/manage.h
+++ b/manage.h
@@ -174,6 +174,9 @@ struct management_callback
#if HTTP_PROXY_FALLBACK
bool (*http_proxy_fallback_cmd) (void *arg, const char *server, const char *port, const char *flags);
#endif
+#if MANAGEMENT_QUERY_REMOTE
+ bool (*remote_cmd) (void *arg, const char **p);
+#endif
};
/*
@@ -333,6 +336,9 @@ struct management *management_init (void);
# define MF_EXTERNAL_KEY (1<<9)
#endif
#define MF_UP_DOWN (1<<10)
+#if MANAGEMENT_QUERY_REMOTE
+#define MF_QUERY_REMOTE (1<<11)
+#endif
bool management_open (struct management *man,
const char *addr,
@@ -381,6 +387,8 @@ void management_up_down(struct management *man, const char *updown, const struct
void management_notify(struct management *man, const char *severity, const char *type, const char *text);
+void management_notify_generic (struct management *man, const char *str);
+
#ifdef MANAGEMENT_DEF_AUTH
void management_notify_client_needing_auth (struct management *management,
const unsigned int auth_id,
@@ -419,6 +427,14 @@ management_query_user_pass_enabled (const struct management *man)
return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
}
+#if MANAGEMENT_QUERY_REMOTE
+static inline bool
+management_query_remote_enabled (const struct management *man)
+{
+ return BOOL_CAST(man->settings.flags & MF_QUERY_REMOTE);
+}
+#endif
+
#ifdef MANAGEMENT_PF
static inline bool
management_enable_pf (const struct management *man)
diff --git a/management/management-notes.txt b/management/management-notes.txt
index 6e1e7cd..c25c998 100644
--- a/management/management-notes.txt
+++ b/management/management-notes.txt
@@ -687,6 +687,38 @@ the 10.0.0.0/8 netblock is allowed: 10.10.0.1. Also, the client
may not interact with external IP addresses using an "unknown"
protocol (i.e. one that is not IPv4 or ARP).
+COMMAND -- remote (OpenVPN 2.1.4 or higher)
+--------------------------------------------
+
+Provide remote host/port in response to a >REMOTE notification
+(client only). Requires that the --management-query-remote
+directive is used.
+
+ remote ACTION [HOST PORT]
+
+The "remote" command should only be given in response to a >REMOTE
+notification. For example, the following >REMOTE notification
+indicates that the client config file would ordinarily connect
+to vpn.example.com port 1194 (UDP):
+
+ >REMOTE:vpn.example.com,1194,udp
+
+Now, suppose we want to override the host and port, connecting
+instead to vpn.otherexample.com port 1234. After receiving
+the above notification, use this command:
+
+ remote MOD vpn.otherexample.com 1234
+
+To accept the same host and port as the client would ordinarily
+have connected to, use this command:
+
+ remote ACCEPT
+
+To skip the current connection entry and advance to the next one,
+use this command:
+
+ remote SKIP
+
OUTPUT FORMAT
-------------
diff --git a/openvpn.8 b/openvpn.8
index 1c5ca0d..8705869 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -2370,6 +2370,12 @@ for inputs which ordinarily would have been queried from the
console.
.\"*********************************************************
.TP
+.B --management-query-remote
+Allow management interface to override
+.B --remote
+directives (client-only).
+.\"*********************************************************
+.TP
.B --management-forget-disconnect
Make OpenVPN forget passwords when management session
disconnects.
diff --git a/options.c b/options.c
index bbd0be5..88ed45d 100644
--- a/options.c
+++ b/options.c
@@ -339,6 +339,9 @@ static const char usage_message[] =
" ip/port rather than listen as a TCP server.\n"
"--management-query-passwords : Query management channel for private key\n"
" and auth-user-pass passwords.\n"
+#if MANAGEMENT_QUERY_REMOTE
+ "--management-query-remote : Query management channel for --remote directive.\n"
+#endif
"--management-hold : Start " PACKAGE_NAME " in a hibernating state, until a client\n"
" of the management interface explicitly starts it.\n"
"--management-signal : Issue SIGUSR1 when management disconnect event occurs.\n"
@@ -3705,6 +3708,13 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL);
options->management_flags |= MF_QUERY_PASSWORDS;
}
+#if MANAGEMENT_QUERY_REMOTE
+ else if (streq (p[0], "management-query-remote"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->management_flags |= MF_QUERY_REMOTE;
+ }
+#endif
else if (streq (p[0], "management-hold"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/options.h b/options.h
index 34bacec..f426e2a 100644
--- a/options.h
+++ b/options.h
@@ -109,7 +109,15 @@ struct connection_entry
# define CE_HTTP_PROXY_FALLBACK (1<<1)
time_t ce_http_proxy_fallback_timestamp; /* time when fallback http_proxy_options was last updated */
#endif
-
+#if MANAGEMENT_QUERY_REMOTE
+# define CE_MAN_QUERY_REMOTE_UNDEF 0
+# define CE_MAN_QUERY_REMOTE_QUERY 1
+# define CE_MAN_QUERY_REMOTE_ACCEPT 2
+# define CE_MAN_QUERY_REMOTE_MOD 3
+# define CE_MAN_QUERY_REMOTE_SKIP 4
+# define CE_MAN_QUERY_REMOTE_MASK (0x07)
+# define CE_MAN_QUERY_REMOTE_SHIFT (2)
+#endif
unsigned int flags;
};
@@ -149,6 +157,14 @@ struct hpo_store
};
#endif
+#if MANAGEMENT_QUERY_REMOTE
+struct remote_host_store
+{
+# define RH_HOST_LEN 80
+ char host[RH_HOST_LEN];
+};
+#endif
+
/* Command line options */
struct options
{
@@ -201,6 +217,10 @@ struct options
struct hpo_store *hpo_store; /* used to store dynamic proxy info given by management interface */
#endif
+#if MANAGEMENT_QUERY_REMOTE
+ struct remote_host_store *rh_store;
+#endif
+
bool remote_random;
const char *ipchange;
const char *dev;
diff --git a/syshead.h b/syshead.h
index 038b484..3cc6c3f 100644
--- a/syshead.h
+++ b/syshead.h
@@ -661,6 +661,15 @@ socket_defined (const socket_descriptor_t sd)
#endif
/*
+ * Should we include --management-query-remote functionality
+ */
+#if defined(ENABLE_CONNECTION) && defined(ENABLE_MANAGEMENT)
+#define MANAGEMENT_QUERY_REMOTE 1
+#else
+#define MANAGEMENT_QUERY_REMOTE 0
+#endif
+
+/*
* Reduce sensitivity to system clock instability
* and backtracks.
*/
diff --git a/version.m4 b/version.m4
index 2b11a63..c1122e5 100644
--- a/version.m4
+++ b/version.m4
@@ -1,5 +1,5 @@
dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1.3z])
+define(PRODUCT_VERSION,[2.1.4])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])