diff options
author | James Yonan | 2011-07-05 00:33:55 +0000 |
---|---|---|
committer | James Yonan | 2011-07-05 00:33:55 +0000 |
commit | 54561af63699e7408fba11c75bbf9e22ed6216dc (patch) | |
tree | f75b352719fab8367306b383a18fc6779beeae7c | |
parent | 5cdb5e0111df7b3d4da7e28390af6e4f26b2cdbe (diff) | |
download | openvpn-54561af63699e7408fba11c75bbf9e22ed6216dc.zip openvpn-54561af63699e7408fba11c75bbf9e22ed6216dc.tar.gz |
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.c | 116 | ||||
-rw-r--r-- | manage.c | 41 | ||||
-rw-r--r-- | manage.h | 16 | ||||
-rw-r--r-- | management/management-notes.txt | 32 | ||||
-rw-r--r-- | openvpn.8 | 6 | ||||
-rw-r--r-- | options.c | 10 | ||||
-rw-r--r-- | options.h | 22 | ||||
-rw-r--r-- | syshead.h | 9 | ||||
-rw-r--r-- | version.m4 | 2 |
9 files changed, 242 insertions, 12 deletions
@@ -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); @@ -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 @@ -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 ------------- @@ -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. @@ -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); @@ -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; @@ -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. */ @@ -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]) |