git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5652 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -724,6 +724,12 @@ void gc_transfer (struct gc_arena *dest, struct gc_arena *src); |
| 724 | 724 |
|
| 725 | 725 |
void x_gc_free (struct gc_arena *a); |
| 726 | 726 |
|
| 727 |
+static inline bool |
|
| 728 |
+gc_defined (struct gc_arena *a) |
|
| 729 |
+{
|
|
| 730 |
+ return a->list != NULL; |
|
| 731 |
+} |
|
| 732 |
+ |
|
| 727 | 733 |
static inline void |
| 728 | 734 |
gc_init (struct gc_arena *a) |
| 729 | 735 |
{
|
| ... | ... |
@@ -687,14 +687,25 @@ read_incoming_link (struct context *c) |
| 687 | 687 |
if (c->options.inetd) |
| 688 | 688 |
{
|
| 689 | 689 |
c->sig->signal_received = SIGTERM; |
| 690 |
+ c->sig->signal_text = "connection-reset-inetd"; |
|
| 690 | 691 |
msg (D_STREAM_ERRORS, "Connection reset, inetd/xinetd exit [%d]", status); |
| 691 | 692 |
} |
| 692 | 693 |
else |
| 693 | 694 |
{
|
| 694 |
- c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- TCP connection reset */ |
|
| 695 |
- msg (D_STREAM_ERRORS, "Connection reset, restarting [%d]", status); |
|
| 695 |
+#ifdef ENABLE_OCC |
|
| 696 |
+ if (event_timeout_defined(&c->c2.explicit_exit_notification_interval)) |
|
| 697 |
+ {
|
|
| 698 |
+ msg (D_STREAM_ERRORS, "Connection reset during exit notification period, ignoring [%d]", status); |
|
| 699 |
+ openvpn_sleep(1); |
|
| 700 |
+ } |
|
| 701 |
+ else |
|
| 702 |
+#endif |
|
| 703 |
+ {
|
|
| 704 |
+ c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- TCP connection reset */ |
|
| 705 |
+ c->sig->signal_text = "connection-reset"; |
|
| 706 |
+ msg (D_STREAM_ERRORS, "Connection reset, restarting [%d]", status); |
|
| 707 |
+ } |
|
| 696 | 708 |
} |
| 697 |
- c->sig->signal_text = "connection-reset"; |
|
| 698 | 709 |
} |
| 699 | 710 |
perf_pop (); |
| 700 | 711 |
return; |
| ... | ... |
@@ -111,6 +111,103 @@ update_options_ce_post (struct options *options) |
| 111 | 111 |
#endif |
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 |
+#if HTTP_PROXY_FALLBACK |
|
| 115 |
+ |
|
| 116 |
+static bool |
|
| 117 |
+ce_http_proxy_fallback_defined(const struct context *c) |
|
| 118 |
+{
|
|
| 119 |
+ const struct connection_list *l = c->options.connection_list; |
|
| 120 |
+ if (l && l->current == 0) |
|
| 121 |
+ {
|
|
| 122 |
+ int i; |
|
| 123 |
+ for (i = 0; i < l->len; ++i) |
|
| 124 |
+ {
|
|
| 125 |
+ if (l->array[i]->flags & CE_HTTP_PROXY_FALLBACK) |
|
| 126 |
+ return true; |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ return false; |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+static void |
|
| 133 |
+ce_http_proxy_fallback_start(struct context *c, const char *remote_ip_hint) |
|
| 134 |
+{
|
|
| 135 |
+ const struct connection_list *l = c->options.connection_list; |
|
| 136 |
+ if (l) |
|
| 137 |
+ {
|
|
| 138 |
+ int i; |
|
| 139 |
+ for (i = 0; i < l->len; ++i) |
|
| 140 |
+ {
|
|
| 141 |
+ struct connection_entry *ce = l->array[i]; |
|
| 142 |
+ if (ce->flags & CE_HTTP_PROXY_FALLBACK) |
|
| 143 |
+ {
|
|
| 144 |
+ ce->http_proxy_options = NULL; |
|
| 145 |
+ ce->ce_http_proxy_fallback_timestamp = 0; |
|
| 146 |
+ if (!remote_ip_hint) |
|
| 147 |
+ remote_ip_hint = ce->remote; |
|
| 148 |
+ } |
|
| 149 |
+ } |
|
| 150 |
+ } |
|
| 151 |
+ |
|
| 152 |
+ if (management) |
|
| 153 |
+ management_http_proxy_fallback_notify(management, "NEED_LATER", remote_ip_hint); |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+static bool |
|
| 157 |
+ce_http_proxy_fallback (struct context *c, volatile const struct connection_entry *ce) |
|
| 158 |
+{
|
|
| 159 |
+ const int proxy_info_expire = 120; /* seconds before proxy info expires */ |
|
| 160 |
+ |
|
| 161 |
+ update_time(); |
|
| 162 |
+ if (management) |
|
| 163 |
+ {
|
|
| 164 |
+ if (!ce->ce_http_proxy_fallback_timestamp) |
|
| 165 |
+ {
|
|
| 166 |
+ management_http_proxy_fallback_notify(management, "NEED_NOW", NULL); |
|
| 167 |
+ while (!ce->ce_http_proxy_fallback_timestamp) |
|
| 168 |
+ {
|
|
| 169 |
+ management_event_loop_n_seconds (management, 1); |
|
| 170 |
+ if (IS_SIG (c)) |
|
| 171 |
+ return false; |
|
| 172 |
+ } |
|
| 173 |
+ } |
|
| 174 |
+ return (now < ce->ce_http_proxy_fallback_timestamp + proxy_info_expire && ce->http_proxy_options); |
|
| 175 |
+ } |
|
| 176 |
+ return false; |
|
| 177 |
+} |
|
| 178 |
+ |
|
| 179 |
+static bool |
|
| 180 |
+management_callback_http_proxy_fallback_cmd (void *arg, const char *server, const char *port, const char *flags) |
|
| 181 |
+{
|
|
| 182 |
+ struct context *c = (struct context *) arg; |
|
| 183 |
+ const struct connection_list *l = c->options.connection_list; |
|
| 184 |
+ int ret = false; |
|
| 185 |
+ struct http_proxy_options *ho = parse_http_proxy_fallback (c, server, port, flags, M_WARN); |
|
| 186 |
+ |
|
| 187 |
+ update_time(); |
|
| 188 |
+ if (l) |
|
| 189 |
+ {
|
|
| 190 |
+ int i; |
|
| 191 |
+ for (i = 0; i < l->len; ++i) |
|
| 192 |
+ {
|
|
| 193 |
+ struct connection_entry *ce = l->array[i]; |
|
| 194 |
+ if (ce->flags & CE_HTTP_PROXY_FALLBACK) |
|
| 195 |
+ {
|
|
| 196 |
+ if (ho) |
|
| 197 |
+ {
|
|
| 198 |
+ ce->http_proxy_options = ho; |
|
| 199 |
+ ret = true; |
|
| 200 |
+ } |
|
| 201 |
+ ce->ce_http_proxy_fallback_timestamp = now; |
|
| 202 |
+ } |
|
| 203 |
+ } |
|
| 204 |
+ } |
|
| 205 |
+ |
|
| 206 |
+ return ret; |
|
| 207 |
+} |
|
| 208 |
+ |
|
| 209 |
+#endif |
|
| 210 |
+ |
|
| 114 | 211 |
/* |
| 115 | 212 |
* Initialize and possibly randomize connection list. |
| 116 | 213 |
*/ |
| ... | ... |
@@ -141,6 +238,30 @@ init_connection_list (struct context *c) |
| 141 | 141 |
#endif |
| 142 | 142 |
} |
| 143 | 143 |
|
| 144 |
+#if 0 /* fixme -- disable for production */ |
|
| 145 |
+static void |
|
| 146 |
+show_connection_list (const struct connection_list *l) |
|
| 147 |
+{
|
|
| 148 |
+ int i; |
|
| 149 |
+ dmsg (M_INFO, "CONNECTION_LIST len=%d current=%d", |
|
| 150 |
+ l->len, l->current); |
|
| 151 |
+ for (i = 0; i < l->len; ++i) |
|
| 152 |
+ {
|
|
| 153 |
+ dmsg (M_INFO, "[%d] %s:%d proto=%s http_proxy=%d", |
|
| 154 |
+ i, |
|
| 155 |
+ l->array[i]->remote, |
|
| 156 |
+ l->array[i]->remote_port, |
|
| 157 |
+ proto2ascii(l->array[i]->proto, true), |
|
| 158 |
+ BOOL_CAST(l->array[i]->http_proxy_options)); |
|
| 159 |
+ } |
|
| 160 |
+} |
|
| 161 |
+#else |
|
| 162 |
+static inline void |
|
| 163 |
+show_connection_list (const struct connection_list *l) |
|
| 164 |
+{
|
|
| 165 |
+} |
|
| 166 |
+#endif |
|
| 167 |
+ |
|
| 144 | 168 |
/* |
| 145 | 169 |
* Increment to next connection entry |
| 146 | 170 |
*/ |
| ... | ... |
@@ -151,27 +272,65 @@ next_connection_entry (struct context *c) |
| 151 | 151 |
struct connection_list *l = c->options.connection_list; |
| 152 | 152 |
if (l) |
| 153 | 153 |
{
|
| 154 |
- if (l->no_advance && l->current >= 0) |
|
| 155 |
- {
|
|
| 156 |
- l->no_advance = false; |
|
| 157 |
- } |
|
| 158 |
- else |
|
| 159 |
- {
|
|
| 160 |
- int i; |
|
| 161 |
- if (++l->current >= l->len) |
|
| 162 |
- l->current = 0; |
|
| 154 |
+ bool ce_defined; |
|
| 155 |
+ struct connection_entry *ce; |
|
| 156 |
+ int n_cycles = 0; |
|
| 163 | 157 |
|
| 164 |
- dmsg (D_CONNECTION_LIST, "CONNECTION_LIST len=%d current=%d", |
|
| 165 |
- l->len, l->current); |
|
| 166 |
- for (i = 0; i < l->len; ++i) |
|
| 167 |
- {
|
|
| 168 |
- dmsg (D_CONNECTION_LIST, "[%d] %s:%d", |
|
| 169 |
- i, |
|
| 170 |
- l->array[i]->remote, |
|
| 171 |
- l->array[i]->remote_port); |
|
| 172 |
- } |
|
| 173 |
- } |
|
| 174 |
- c->options.ce = *l->array[l->current]; |
|
| 158 |
+ do {
|
|
| 159 |
+ const char *remote_ip_hint = NULL; |
|
| 160 |
+ bool advanced = false; |
|
| 161 |
+ |
|
| 162 |
+ ce_defined = true; |
|
| 163 |
+ if (l->no_advance && l->current >= 0) |
|
| 164 |
+ {
|
|
| 165 |
+ l->no_advance = false; |
|
| 166 |
+ } |
|
| 167 |
+ else |
|
| 168 |
+ {
|
|
| 169 |
+ if (++l->current >= l->len) |
|
| 170 |
+ {
|
|
| 171 |
+ l->current = 0; |
|
| 172 |
+ ++l->n_cycles; |
|
| 173 |
+ if (++n_cycles >= 2) |
|
| 174 |
+ msg (M_FATAL, "No usable connection profiles are present"); |
|
| 175 |
+ } |
|
| 176 |
+ |
|
| 177 |
+ advanced = true; |
|
| 178 |
+ show_connection_list(l); |
|
| 179 |
+ } |
|
| 180 |
+ |
|
| 181 |
+ ce = l->array[l->current]; |
|
| 182 |
+ |
|
| 183 |
+ if (c->options.remote_ip_hint && !l->n_cycles) |
|
| 184 |
+ remote_ip_hint = c->options.remote_ip_hint; |
|
| 185 |
+ |
|
| 186 |
+#if HTTP_PROXY_FALLBACK |
|
| 187 |
+ if (advanced && ce_http_proxy_fallback_defined(c)) |
|
| 188 |
+ ce_http_proxy_fallback_start(c, remote_ip_hint); |
|
| 189 |
+ |
|
| 190 |
+ if (ce->flags & CE_HTTP_PROXY_FALLBACK) |
|
| 191 |
+ {
|
|
| 192 |
+ ce_defined = ce_http_proxy_fallback(c, ce); |
|
| 193 |
+ if (IS_SIG (c)) |
|
| 194 |
+ break; |
|
| 195 |
+ } |
|
| 196 |
+#endif |
|
| 197 |
+ |
|
| 198 |
+ if (ce->flags & CE_DISABLED) |
|
| 199 |
+ ce_defined = false; |
|
| 200 |
+ |
|
| 201 |
+ c->options.ce = *ce; |
|
| 202 |
+ |
|
| 203 |
+ if (remote_ip_hint) |
|
| 204 |
+ c->options.ce.remote = remote_ip_hint; |
|
| 205 |
+ |
|
| 206 |
+#if 0 /* fixme -- disable for production, this code simulates a network where proxy fallback is the only method to reach the OpenVPN server */ |
|
| 207 |
+ if (!(c->options.ce.flags & CE_HTTP_PROXY_FALLBACK)) |
|
| 208 |
+ {
|
|
| 209 |
+ c->options.ce.remote = "10.10.0.1"; /* use an unreachable address here */ |
|
| 210 |
+ } |
|
| 211 |
+#endif |
|
| 212 |
+ } while (!ce_defined); |
|
| 175 | 213 |
} |
| 176 | 214 |
#endif |
| 177 | 215 |
update_options_ce_post (&c->options); |
| ... | ... |
@@ -2774,6 +2933,9 @@ init_management_callback_p2p (struct context *c) |
| 2774 | 2774 |
cb.arg = c; |
| 2775 | 2775 |
cb.status = management_callback_status_p2p; |
| 2776 | 2776 |
cb.show_net = management_show_net_callback; |
| 2777 |
+#if HTTP_PROXY_FALLBACK |
|
| 2778 |
+ cb.http_proxy_fallback_cmd = management_callback_http_proxy_fallback_cmd; |
|
| 2779 |
+#endif |
|
| 2777 | 2780 |
management_set_callback (management, &cb); |
| 2778 | 2781 |
} |
| 2779 | 2782 |
#endif |
| ... | ... |
@@ -2898,6 +3060,17 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int |
| 2898 | 2898 |
c->sig->signal_text = NULL; |
| 2899 | 2899 |
c->sig->hard = false; |
| 2900 | 2900 |
|
| 2901 |
+ if (c->mode == CM_P2P) |
|
| 2902 |
+ init_management_callback_p2p (c); |
|
| 2903 |
+ |
|
| 2904 |
+ /* possible sleep or management hold if restart */ |
|
| 2905 |
+ if (c->mode == CM_P2P || c->mode == CM_TOP) |
|
| 2906 |
+ {
|
|
| 2907 |
+ do_startup_pause (c); |
|
| 2908 |
+ if (IS_SIG (c)) |
|
| 2909 |
+ goto sig; |
|
| 2910 |
+ } |
|
| 2911 |
+ |
|
| 2901 | 2912 |
/* map in current connection entry */ |
| 2902 | 2913 |
next_connection_entry (c); |
| 2903 | 2914 |
|
| ... | ... |
@@ -2916,14 +3089,6 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int |
| 2916 | 2916 |
if (c->first_time && options->mlock) |
| 2917 | 2917 |
do_mlockall (true); |
| 2918 | 2918 |
|
| 2919 |
- /* possible sleep or management hold if restart */ |
|
| 2920 |
- if (c->mode == CM_P2P || c->mode == CM_TOP) |
|
| 2921 |
- {
|
|
| 2922 |
- do_startup_pause (c); |
|
| 2923 |
- if (IS_SIG (c)) |
|
| 2924 |
- goto sig; |
|
| 2925 |
- } |
|
| 2926 |
- |
|
| 2927 | 2919 |
#if P2MP |
| 2928 | 2920 |
/* get passwords if undefined */ |
| 2929 | 2921 |
if (auth_retry_get () == AR_INTERACT) |
| ... | ... |
@@ -110,6 +110,10 @@ man_help () |
| 110 | 110 |
msg (M_CLIENT, "username type u : Enter username u for a queried OpenVPN username."); |
| 111 | 111 |
msg (M_CLIENT, "verb [n] : Set log verbosity level to n, or show if n is absent."); |
| 112 | 112 |
msg (M_CLIENT, "version : Show current version number."); |
| 113 |
+#if HTTP_PROXY_FALLBACK |
|
| 114 |
+ msg (M_CLIENT, "http-proxy-fallback <server> <port> [flags] : Enter dynamic HTTP proxy fallback info."); |
|
| 115 |
+ msg (M_CLIENT, "http-proxy-fallback-disable : Disable HTTP proxy fallback."); |
|
| 116 |
+#endif |
|
| 113 | 117 |
msg (M_CLIENT, "END"); |
| 114 | 118 |
} |
| 115 | 119 |
|
| ... | ... |
@@ -204,12 +208,10 @@ man_update_io_state (struct management *man) |
| 204 | 204 |
} |
| 205 | 205 |
|
| 206 | 206 |
static void |
| 207 |
-man_output_list_push (struct management *man, const char *str) |
|
| 207 |
+man_output_list_push_finalize (struct management *man) |
|
| 208 | 208 |
{
|
| 209 | 209 |
if (management_connected (man)) |
| 210 | 210 |
{
|
| 211 |
- if (str) |
|
| 212 |
- buffer_list_push (man->connection.out, (const unsigned char *) str); |
|
| 213 | 211 |
man_update_io_state (man); |
| 214 | 212 |
if (!man->persist.standalone_disabled) |
| 215 | 213 |
{
|
| ... | ... |
@@ -220,6 +222,22 @@ man_output_list_push (struct management *man, const char *str) |
| 220 | 220 |
} |
| 221 | 221 |
|
| 222 | 222 |
static void |
| 223 |
+man_output_list_push_str (struct management *man, const char *str) |
|
| 224 |
+{
|
|
| 225 |
+ if (management_connected (man) && str) |
|
| 226 |
+ {
|
|
| 227 |
+ buffer_list_push (man->connection.out, (const unsigned char *) str); |
|
| 228 |
+ } |
|
| 229 |
+} |
|
| 230 |
+ |
|
| 231 |
+static void |
|
| 232 |
+man_output_list_push (struct management *man, const char *str) |
|
| 233 |
+{
|
|
| 234 |
+ man_output_list_push_str (man, str); |
|
| 235 |
+ man_output_list_push_finalize (man); |
|
| 236 |
+} |
|
| 237 |
+ |
|
| 238 |
+static void |
|
| 223 | 239 |
man_prompt (struct management *man) |
| 224 | 240 |
{
|
| 225 | 241 |
if (man_password_needed (man)) |
| ... | ... |
@@ -256,12 +274,13 @@ man_close_socket (struct management *man, const socket_descriptor_t sd) |
| 256 | 256 |
static void |
| 257 | 257 |
virtual_output_callback_func (void *arg, const unsigned int flags, const char *str) |
| 258 | 258 |
{
|
| 259 |
+ struct management *man = (struct management *) arg; |
|
| 259 | 260 |
static int recursive_level = 0; /* GLOBAL */ |
| 261 |
+ bool did_push = false; |
|
| 260 | 262 |
|
| 261 | 263 |
if (!recursive_level) /* don't allow recursion */ |
| 262 | 264 |
{
|
| 263 | 265 |
struct gc_arena gc = gc_new (); |
| 264 |
- struct management *man = (struct management *) arg; |
|
| 265 | 266 |
struct log_entry e; |
| 266 | 267 |
const char *out = NULL; |
| 267 | 268 |
|
| ... | ... |
@@ -289,13 +308,17 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s |
| 289 | 289 |
| LOG_PRINT_LOG_PREFIX |
| 290 | 290 |
| LOG_PRINT_CRLF, &gc); |
| 291 | 291 |
if (out) |
| 292 |
- man_output_list_push (man, out); |
|
| 292 |
+ {
|
|
| 293 |
+ man_output_list_push_str (man, out); |
|
| 294 |
+ did_push = true; |
|
| 295 |
+ } |
|
| 293 | 296 |
if (flags & M_FATAL) |
| 294 | 297 |
{
|
| 295 | 298 |
out = log_entry_print (&e, LOG_FATAL_NOTIFY|LOG_PRINT_CRLF, &gc); |
| 296 | 299 |
if (out) |
| 297 | 300 |
{
|
| 298 |
- man_output_list_push (man, out); |
|
| 301 |
+ man_output_list_push_str (man, out); |
|
| 302 |
+ did_push = true; |
|
| 299 | 303 |
man_reset_client_socket (man, true); |
| 300 | 304 |
} |
| 301 | 305 |
} |
| ... | ... |
@@ -304,6 +327,9 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s |
| 304 | 304 |
--recursive_level; |
| 305 | 305 |
gc_free (&gc); |
| 306 | 306 |
} |
| 307 |
+ |
|
| 308 |
+ if (did_push) |
|
| 309 |
+ man_output_list_push_finalize (man); |
|
| 307 | 310 |
} |
| 308 | 311 |
|
| 309 | 312 |
/* |
| ... | ... |
@@ -998,6 +1024,31 @@ man_need (struct management *man, const char **p, const int n, unsigned int flag |
| 998 | 998 |
return true; |
| 999 | 999 |
} |
| 1000 | 1000 |
|
| 1001 |
+#if HTTP_PROXY_FALLBACK |
|
| 1002 |
+ |
|
| 1003 |
+static void |
|
| 1004 |
+man_http_proxy_fallback (struct management *man, const char *server, const char *port, const char *flags) |
|
| 1005 |
+{
|
|
| 1006 |
+ if (man->persist.callback.http_proxy_fallback_cmd) |
|
| 1007 |
+ {
|
|
| 1008 |
+ const bool status = (*man->persist.callback.http_proxy_fallback_cmd)(man->persist.callback.arg, server, port, flags); |
|
| 1009 |
+ if (status) |
|
| 1010 |
+ {
|
|
| 1011 |
+ msg (M_CLIENT, "SUCCESS: proxy-fallback command succeeded"); |
|
| 1012 |
+ } |
|
| 1013 |
+ else |
|
| 1014 |
+ {
|
|
| 1015 |
+ msg (M_CLIENT, "ERROR: proxy-fallback command failed"); |
|
| 1016 |
+ } |
|
| 1017 |
+ } |
|
| 1018 |
+ else |
|
| 1019 |
+ {
|
|
| 1020 |
+ msg (M_CLIENT, "ERROR: The proxy-fallback command is not supported by the current daemon mode"); |
|
| 1021 |
+ } |
|
| 1022 |
+} |
|
| 1023 |
+ |
|
| 1024 |
+#endif |
|
| 1025 |
+ |
|
| 1001 | 1026 |
static void |
| 1002 | 1027 |
man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms) |
| 1003 | 1028 |
{
|
| ... | ... |
@@ -1210,6 +1261,17 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch |
| 1210 | 1210 |
man_pkcs11_id_get (man, atoi(p[1])); |
| 1211 | 1211 |
} |
| 1212 | 1212 |
#endif |
| 1213 |
+#if HTTP_PROXY_FALLBACK |
|
| 1214 |
+ else if (streq (p[0], "http-proxy-fallback")) |
|
| 1215 |
+ {
|
|
| 1216 |
+ if (man_need (man, p, 2, MN_AT_LEAST)) |
|
| 1217 |
+ man_http_proxy_fallback (man, p[1], p[2], p[3]); |
|
| 1218 |
+ } |
|
| 1219 |
+ else if (streq (p[0], "http-proxy-fallback-disable")) |
|
| 1220 |
+ {
|
|
| 1221 |
+ man_http_proxy_fallback (man, NULL, NULL, NULL); |
|
| 1222 |
+ } |
|
| 1223 |
+#endif |
|
| 1213 | 1224 |
#if 1 |
| 1214 | 1225 |
else if (streq (p[0], "test")) |
| 1215 | 1226 |
{
|
| ... | ... |
@@ -2103,7 +2165,7 @@ management_clear_callback (struct management *man) |
| 2103 | 2103 |
man->persist.standalone_disabled = false; |
| 2104 | 2104 |
man->persist.hold_release = false; |
| 2105 | 2105 |
CLEAR (man->persist.callback); |
| 2106 |
- man_output_list_push (man, NULL); /* flush output queue */ |
|
| 2106 |
+ man_output_list_push_finalize (man); /* flush output queue */ |
|
| 2107 | 2107 |
} |
| 2108 | 2108 |
|
| 2109 | 2109 |
void |
| ... | ... |
@@ -2402,7 +2464,7 @@ management_io (struct management *man) |
| 2402 | 2402 |
net_event_win32_clear_selected_events (&man->connection.ne32, FD_ACCEPT); |
| 2403 | 2403 |
} |
| 2404 | 2404 |
} |
| 2405 |
- else if (man->connection.state == MS_CC_WAIT_READ) |
|
| 2405 |
+ else if (man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE) |
|
| 2406 | 2406 |
{
|
| 2407 | 2407 |
if (net_events & FD_READ) |
| 2408 | 2408 |
{
|
| ... | ... |
@@ -2410,18 +2472,13 @@ management_io (struct management *man) |
| 2410 | 2410 |
; |
| 2411 | 2411 |
net_event_win32_clear_selected_events (&man->connection.ne32, FD_READ); |
| 2412 | 2412 |
} |
| 2413 |
- } |
|
| 2414 | 2413 |
|
| 2415 |
- if (man->connection.state == MS_CC_WAIT_WRITE) |
|
| 2416 |
- {
|
|
| 2417 | 2414 |
if (net_events & FD_WRITE) |
| 2418 | 2415 |
{
|
| 2419 | 2416 |
int status; |
| 2420 |
- /* dmsg (M_INFO, "FD_WRITE set"); */ |
|
| 2421 | 2417 |
status = man_write (man); |
| 2422 | 2418 |
if (status < 0 && WSAGetLastError() == WSAEWOULDBLOCK) |
| 2423 | 2419 |
{
|
| 2424 |
- /* dmsg (M_INFO, "FD_WRITE cleared"); */ |
|
| 2425 | 2420 |
net_event_win32_clear_selected_events (&man->connection.ne32, FD_WRITE); |
| 2426 | 2421 |
} |
| 2427 | 2422 |
} |
| ... | ... |
@@ -2512,7 +2569,7 @@ man_block (struct management *man, volatile int *signal_received, const time_t e |
| 2512 | 2512 |
|
| 2513 | 2513 |
if (man_standalone_ok (man)) |
| 2514 | 2514 |
{
|
| 2515 |
- do |
|
| 2515 |
+ while (true) |
|
| 2516 | 2516 |
{
|
| 2517 | 2517 |
event_reset (man->connection.es); |
| 2518 | 2518 |
management_socket_set (man, man->connection.es, NULL, NULL); |
| ... | ... |
@@ -2530,15 +2587,18 @@ man_block (struct management *man, volatile int *signal_received, const time_t e |
| 2530 | 2530 |
status = -1; |
| 2531 | 2531 |
break; |
| 2532 | 2532 |
} |
| 2533 |
- /* set SIGINT signal if expiration time exceeded */ |
|
| 2534 |
- if (expire && now >= expire) |
|
| 2533 |
+ |
|
| 2534 |
+ if (status > 0) |
|
| 2535 |
+ break; |
|
| 2536 |
+ else if (expire && now >= expire) |
|
| 2535 | 2537 |
{
|
| 2538 |
+ /* set SIGINT signal if expiration time exceeded */ |
|
| 2536 | 2539 |
status = 0; |
| 2537 | 2540 |
if (signal_received) |
| 2538 | 2541 |
*signal_received = SIGINT; |
| 2539 | 2542 |
break; |
| 2540 | 2543 |
} |
| 2541 |
- } while (status != 1); |
|
| 2544 |
+ } |
|
| 2542 | 2545 |
} |
| 2543 | 2546 |
return status; |
| 2544 | 2547 |
} |
| ... | ... |
@@ -2615,28 +2675,29 @@ management_event_loop_n_seconds (struct management *man, int sec) |
| 2615 | 2615 |
{
|
| 2616 | 2616 |
volatile int signal_received = 0; |
| 2617 | 2617 |
const bool standalone_disabled_save = man->persist.standalone_disabled; |
| 2618 |
- time_t expire; |
|
| 2618 |
+ time_t expire = 0; |
|
| 2619 | 2619 |
|
| 2620 | 2620 |
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */ |
| 2621 | 2621 |
|
| 2622 | 2622 |
/* set expire time */ |
| 2623 | 2623 |
update_time (); |
| 2624 |
- expire = now + sec; |
|
| 2624 |
+ if (sec) |
|
| 2625 |
+ expire = now + sec; |
|
| 2625 | 2626 |
|
| 2626 | 2627 |
/* if no client connection, wait for one */ |
| 2627 | 2628 |
man_wait_for_client_connection (man, &signal_received, expire, 0); |
| 2628 | 2629 |
if (signal_received) |
| 2629 | 2630 |
return; |
| 2630 | 2631 |
|
| 2631 |
- /* run command processing event loop until we get our username/password */ |
|
| 2632 |
- while (true) |
|
| 2632 |
+ /* run command processing event loop */ |
|
| 2633 |
+ do |
|
| 2633 | 2634 |
{
|
| 2634 | 2635 |
man_standalone_event_loop (man, &signal_received, expire); |
| 2635 | 2636 |
if (!signal_received) |
| 2636 | 2637 |
man_check_for_signals (&signal_received); |
| 2637 | 2638 |
if (signal_received) |
| 2638 | 2639 |
return; |
| 2639 |
- } |
|
| 2640 |
+ } while (expire); |
|
| 2640 | 2641 |
|
| 2641 | 2642 |
/* revert state */ |
| 2642 | 2643 |
man->persist.standalone_disabled = standalone_disabled_save; |
| ... | ... |
@@ -3028,6 +3089,19 @@ log_history_ref (const struct log_history *h, const int index) |
| 3028 | 3028 |
return NULL; |
| 3029 | 3029 |
} |
| 3030 | 3030 |
|
| 3031 |
+#if HTTP_PROXY_FALLBACK |
|
| 3032 |
+ |
|
| 3033 |
+void |
|
| 3034 |
+management_http_proxy_fallback_notify (struct management *man, const char *type, const char *remote_ip_hint) |
|
| 3035 |
+{
|
|
| 3036 |
+ if (remote_ip_hint) |
|
| 3037 |
+ msg (M_CLIENT, ">PROXY:%s,%s", type, remote_ip_hint); |
|
| 3038 |
+ else |
|
| 3039 |
+ msg (M_CLIENT, ">PROXY:%s", type); |
|
| 3040 |
+} |
|
| 3041 |
+ |
|
| 3042 |
+#endif /* HTTP_PROXY_FALLBACK */ |
|
| 3043 |
+ |
|
| 3031 | 3044 |
#else |
| 3032 | 3045 |
static void dummy(void) {}
|
| 3033 | 3046 |
#endif /* ENABLE_MANAGEMENT */ |
| ... | ... |
@@ -170,6 +170,9 @@ struct management_callback |
| 170 | 170 |
const unsigned long cid, |
| 171 | 171 |
struct buffer_list *pf_config); /* ownership transferred */ |
| 172 | 172 |
#endif |
| 173 |
+#if HTTP_PROXY_FALLBACK |
|
| 174 |
+ bool (*http_proxy_fallback_cmd) (void *arg, const char *server, const char *port, const char *flags); |
|
| 175 |
+#endif |
|
| 173 | 176 |
}; |
| 174 | 177 |
|
| 175 | 178 |
/* |
| ... | ... |
@@ -502,5 +505,11 @@ management_bytes_server (struct management *man, |
| 502 | 502 |
|
| 503 | 503 |
#endif /* MANAGEMENT_DEF_AUTH */ |
| 504 | 504 |
|
| 505 |
+#if HTTP_PROXY_FALLBACK |
|
| 506 |
+ |
|
| 507 |
+void management_http_proxy_fallback_notify (struct management *man, const char *type, const char *remote_ip_hint); |
|
| 508 |
+ |
|
| 509 |
+#endif /* HTTP_PROXY_FALLBACK */ |
|
| 510 |
+ |
|
| 505 | 511 |
#endif |
| 506 | 512 |
#endif |
| ... | ... |
@@ -1374,6 +1374,9 @@ get_user_pass (struct user_pass *up, |
| 1374 | 1374 |
{
|
| 1375 | 1375 |
const bool from_stdin = (!auth_file || !strcmp (auth_file, "stdin")); |
| 1376 | 1376 |
|
| 1377 |
+ if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) |
|
| 1378 |
+ msg (M_WARN, "Note: previous '%s' credentials failed", prefix); |
|
| 1379 |
+ |
|
| 1377 | 1380 |
#ifdef ENABLE_MANAGEMENT |
| 1378 | 1381 |
/* |
| 1379 | 1382 |
* Get username/password from standard input? |
| ... | ... |
@@ -1382,6 +1385,9 @@ get_user_pass (struct user_pass *up, |
| 1382 | 1382 |
&& ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT))) |
| 1383 | 1383 |
&& management_query_user_pass_enabled (management)) |
| 1384 | 1384 |
{
|
| 1385 |
+ if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) |
|
| 1386 |
+ management_auth_failure (management, prefix, "previous auth credentials failed"); |
|
| 1387 |
+ |
|
| 1385 | 1388 |
if (!management_query_user_pass (management, up, prefix, flags)) |
| 1386 | 1389 |
{
|
| 1387 | 1390 |
if ((flags & GET_USER_PASS_NOFATAL) != 0) |
| ... | ... |
@@ -263,12 +263,17 @@ bool get_console_input (const char *prompt, const bool echo, char *input, const |
| 263 | 263 |
#define GET_USER_PASS_NEED_OK (1<<3) |
| 264 | 264 |
#define GET_USER_PASS_NOFATAL (1<<4) |
| 265 | 265 |
#define GET_USER_PASS_NEED_STR (1<<5) |
| 266 |
+#define GET_USER_PASS_PREVIOUS_CREDS_FAILED (1<<6) |
|
| 266 | 267 |
|
| 267 | 268 |
bool get_user_pass (struct user_pass *up, |
| 268 | 269 |
const char *auth_file, |
| 269 | 270 |
const char *prefix, |
| 270 | 271 |
const unsigned int flags); |
| 271 | 272 |
|
| 273 |
+void fail_user_pass (const char *prefix, |
|
| 274 |
+ const unsigned int flags, |
|
| 275 |
+ const char *reason); |
|
| 276 |
+ |
|
| 272 | 277 |
void purge_user_pass (struct user_pass *up, const bool force); |
| 273 | 278 |
|
| 274 | 279 |
/* |
| ... | ... |
@@ -761,7 +761,9 @@ void |
| 761 | 761 |
uninit_options (struct options *o) |
| 762 | 762 |
{
|
| 763 | 763 |
if (o->gc_owned) |
| 764 |
- gc_free (&o->gc); |
|
| 764 |
+ {
|
|
| 765 |
+ gc_free (&o->gc); |
|
| 766 |
+ } |
|
| 765 | 767 |
} |
| 766 | 768 |
|
| 767 | 769 |
#ifdef ENABLE_DEBUG |
| ... | ... |
@@ -1412,6 +1414,137 @@ init_http_options_if_undefined (struct options *o) |
| 1412 | 1412 |
|
| 1413 | 1413 |
#endif |
| 1414 | 1414 |
|
| 1415 |
+#if HTTP_PROXY_FALLBACK |
|
| 1416 |
+ |
|
| 1417 |
+static struct http_proxy_options * |
|
| 1418 |
+parse_http_proxy_override (const char *server, |
|
| 1419 |
+ const char *port, |
|
| 1420 |
+ const char *flags, |
|
| 1421 |
+ const int msglevel, |
|
| 1422 |
+ struct gc_arena *gc) |
|
| 1423 |
+{
|
|
| 1424 |
+ if (server && port) |
|
| 1425 |
+ {
|
|
| 1426 |
+ struct http_proxy_options *ho; |
|
| 1427 |
+ const int int_port = atoi(port); |
|
| 1428 |
+ |
|
| 1429 |
+ if (!legal_ipv4_port (int_port)) |
|
| 1430 |
+ {
|
|
| 1431 |
+ msg (msglevel, "Bad http-proxy port number: %s", port); |
|
| 1432 |
+ return NULL; |
|
| 1433 |
+ } |
|
| 1434 |
+ |
|
| 1435 |
+ ALLOC_OBJ_CLEAR_GC (ho, struct http_proxy_options, gc); |
|
| 1436 |
+ ho->server = string_alloc(server, gc); |
|
| 1437 |
+ ho->port = int_port; |
|
| 1438 |
+ ho->retry = true; |
|
| 1439 |
+ ho->timeout = 5; |
|
| 1440 |
+ if (flags && !strcmp(flags, "nct")) |
|
| 1441 |
+ ho->auth_retry = PAR_NCT; |
|
| 1442 |
+ else |
|
| 1443 |
+ ho->auth_retry = PAR_ALL; |
|
| 1444 |
+ ho->http_version = "1.0"; |
|
| 1445 |
+ ho->user_agent = "OpenVPN-Autoproxy/1.0"; |
|
| 1446 |
+ return ho; |
|
| 1447 |
+ } |
|
| 1448 |
+ else |
|
| 1449 |
+ return NULL; |
|
| 1450 |
+} |
|
| 1451 |
+ |
|
| 1452 |
+struct http_proxy_options * |
|
| 1453 |
+parse_http_proxy_fallback (struct context *c, |
|
| 1454 |
+ const char *server, |
|
| 1455 |
+ const char *port, |
|
| 1456 |
+ const char *flags, |
|
| 1457 |
+ const int msglevel) |
|
| 1458 |
+{
|
|
| 1459 |
+ struct gc_arena gc = gc_new (); |
|
| 1460 |
+ struct http_proxy_options *hp = parse_http_proxy_override(server, port, flags, msglevel, &gc); |
|
| 1461 |
+ struct hpo_store *hpos = c->options.hpo_store; |
|
| 1462 |
+ if (!hpos) |
|
| 1463 |
+ {
|
|
| 1464 |
+ ALLOC_OBJ_CLEAR_GC (hpos, struct hpo_store, &c->options.gc); |
|
| 1465 |
+ c->options.hpo_store = hpos; |
|
| 1466 |
+ } |
|
| 1467 |
+ hpos->hpo = *hp; |
|
| 1468 |
+ hpos->hpo.server = hpos->server; |
|
| 1469 |
+ strncpynt(hpos->server, hp->server, sizeof(hpos->server)); |
|
| 1470 |
+ gc_free (&gc); |
|
| 1471 |
+ return &hpos->hpo; |
|
| 1472 |
+} |
|
| 1473 |
+ |
|
| 1474 |
+static void |
|
| 1475 |
+http_proxy_warn(const char *name) |
|
| 1476 |
+{
|
|
| 1477 |
+ msg (M_WARN, "Note: option %s ignored because no TCP-based connection profiles are defined", name); |
|
| 1478 |
+} |
|
| 1479 |
+ |
|
| 1480 |
+void |
|
| 1481 |
+options_postprocess_http_proxy_fallback (struct options *o) |
|
| 1482 |
+{
|
|
| 1483 |
+ struct connection_list *l = o->connection_list; |
|
| 1484 |
+ if (l) |
|
| 1485 |
+ {
|
|
| 1486 |
+ int i; |
|
| 1487 |
+ for (i = 0; i < l->len; ++i) |
|
| 1488 |
+ {
|
|
| 1489 |
+ struct connection_entry *ce = l->array[i]; |
|
| 1490 |
+ if (ce->proto == PROTO_TCPv4_CLIENT || ce->proto == PROTO_TCPv4) |
|
| 1491 |
+ {
|
|
| 1492 |
+ if (l->len < CONNECTION_LIST_SIZE) |
|
| 1493 |
+ {
|
|
| 1494 |
+ struct connection_entry *newce; |
|
| 1495 |
+ ALLOC_OBJ_GC (newce, struct connection_entry, &o->gc); |
|
| 1496 |
+ *newce = *ce; |
|
| 1497 |
+ newce->flags |= CE_HTTP_PROXY_FALLBACK; |
|
| 1498 |
+ newce->http_proxy_options = NULL; |
|
| 1499 |
+ newce->ce_http_proxy_fallback_timestamp = 0; |
|
| 1500 |
+ l->array[l->len++] = newce; |
|
| 1501 |
+ } |
|
| 1502 |
+ return; |
|
| 1503 |
+ } |
|
| 1504 |
+ } |
|
| 1505 |
+ } |
|
| 1506 |
+ http_proxy_warn("http-proxy-fallback");
|
|
| 1507 |
+} |
|
| 1508 |
+ |
|
| 1509 |
+void |
|
| 1510 |
+options_postprocess_http_proxy_override (struct options *o) |
|
| 1511 |
+{
|
|
| 1512 |
+ const struct connection_list *l = o->connection_list; |
|
| 1513 |
+ if (l) |
|
| 1514 |
+ {
|
|
| 1515 |
+ int i; |
|
| 1516 |
+ bool succeed = false; |
|
| 1517 |
+ for (i = 0; i < l->len; ++i) |
|
| 1518 |
+ {
|
|
| 1519 |
+ struct connection_entry *ce = l->array[i]; |
|
| 1520 |
+ if (ce->proto == PROTO_TCPv4_CLIENT || ce->proto == PROTO_TCPv4) |
|
| 1521 |
+ {
|
|
| 1522 |
+ ce->http_proxy_options = o->http_proxy_override; |
|
| 1523 |
+ succeed = true; |
|
| 1524 |
+ } |
|
| 1525 |
+ } |
|
| 1526 |
+ if (succeed) |
|
| 1527 |
+ {
|
|
| 1528 |
+ for (i = 0; i < l->len; ++i) |
|
| 1529 |
+ {
|
|
| 1530 |
+ struct connection_entry *ce = l->array[i]; |
|
| 1531 |
+ if (ce->proto == PROTO_UDPv4) |
|
| 1532 |
+ {
|
|
| 1533 |
+ ce->flags |= CE_DISABLED; |
|
| 1534 |
+ } |
|
| 1535 |
+ } |
|
| 1536 |
+ } |
|
| 1537 |
+ else |
|
| 1538 |
+ {
|
|
| 1539 |
+ http_proxy_warn("http-proxy-override");
|
|
| 1540 |
+ } |
|
| 1541 |
+ } |
|
| 1542 |
+} |
|
| 1543 |
+ |
|
| 1544 |
+#endif |
|
| 1545 |
+ |
|
| 1415 | 1546 |
#if ENABLE_CONNECTION |
| 1416 | 1547 |
|
| 1417 | 1548 |
static struct connection_list * |
| ... | ... |
@@ -2095,7 +2228,7 @@ options_postprocess_mutate (struct options *o) |
| 2095 | 2095 |
* For compatibility with 2.0.x, map multiple --remote options |
| 2096 | 2096 |
* into connection list (connection lists added in 2.1). |
| 2097 | 2097 |
*/ |
| 2098 |
- if (o->remote_list->len > 1) |
|
| 2098 |
+ if (o->remote_list->len > 1 || o->force_connection_list) |
|
| 2099 | 2099 |
{
|
| 2100 | 2100 |
const struct remote_list *rl = o->remote_list; |
| 2101 | 2101 |
int i; |
| ... | ... |
@@ -2112,7 +2245,7 @@ options_postprocess_mutate (struct options *o) |
| 2112 | 2112 |
*ace = ce; |
| 2113 | 2113 |
} |
| 2114 | 2114 |
} |
| 2115 |
- else if (o->remote_list->len == 1) /* one --remote option specfied */ |
|
| 2115 |
+ else if (o->remote_list->len == 1) /* one --remote option specified */ |
|
| 2116 | 2116 |
{
|
| 2117 | 2117 |
connection_entry_load_re (&o->ce, o->remote_list->array[0]); |
| 2118 | 2118 |
} |
| ... | ... |
@@ -2126,6 +2259,13 @@ options_postprocess_mutate (struct options *o) |
| 2126 | 2126 |
int i; |
| 2127 | 2127 |
for (i = 0; i < o->connection_list->len; ++i) |
| 2128 | 2128 |
options_postprocess_mutate_ce (o, o->connection_list->array[i]); |
| 2129 |
+ |
|
| 2130 |
+#if HTTP_PROXY_FALLBACK |
|
| 2131 |
+ if (o->http_proxy_override) |
|
| 2132 |
+ options_postprocess_http_proxy_override(o); |
|
| 2133 |
+ else if (o->http_proxy_fallback) |
|
| 2134 |
+ options_postprocess_http_proxy_fallback(o); |
|
| 2135 |
+#endif |
|
| 2129 | 2136 |
} |
| 2130 | 2137 |
else |
| 2131 | 2138 |
#endif |
| ... | ... |
@@ -3633,11 +3773,29 @@ add_option (struct options *options, |
| 3633 | 3633 |
} |
| 3634 | 3634 |
} |
| 3635 | 3635 |
#endif |
| 3636 |
+#ifdef ENABLE_CONNECTION |
|
| 3636 | 3637 |
else if (streq (p[0], "remote-ip-hint") && p[1]) |
| 3637 | 3638 |
{
|
| 3638 |
- VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION); |
|
| 3639 |
- // fixme |
|
| 3639 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
| 3640 |
+ options->remote_ip_hint = p[1]; |
|
| 3640 | 3641 |
} |
| 3642 |
+#endif |
|
| 3643 |
+#if HTTP_PROXY_FALLBACK |
|
| 3644 |
+ else if (streq (p[0], "http-proxy-fallback")) |
|
| 3645 |
+ {
|
|
| 3646 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
| 3647 |
+ options->http_proxy_fallback = true; |
|
| 3648 |
+ options->force_connection_list = true; |
|
| 3649 |
+ } |
|
| 3650 |
+ else if (streq (p[0], "http-proxy-override") && p[1] && p[2]) |
|
| 3651 |
+ {
|
|
| 3652 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
| 3653 |
+ options->http_proxy_override = parse_http_proxy_override(p[1], p[2], p[3], msglevel, &options->gc); |
|
| 3654 |
+ if (!options->http_proxy_override) |
|
| 3655 |
+ goto err; |
|
| 3656 |
+ options->force_connection_list = true; |
|
| 3657 |
+ } |
|
| 3658 |
+#endif |
|
| 3641 | 3659 |
else if (streq (p[0], "remote") && p[1]) |
| 3642 | 3660 |
{
|
| 3643 | 3661 |
struct remote_entry re; |
| ... | ... |
@@ -97,6 +97,14 @@ struct connection_entry |
| 97 | 97 |
int socks_proxy_port; |
| 98 | 98 |
bool socks_proxy_retry; |
| 99 | 99 |
#endif |
| 100 |
+ |
|
| 101 |
+# define CE_DISABLED (1<<0) |
|
| 102 |
+#if HTTP_PROXY_FALLBACK |
|
| 103 |
+# define CE_HTTP_PROXY_FALLBACK (1<<1) |
|
| 104 |
+ time_t ce_http_proxy_fallback_timestamp; /* time when fallback http_proxy_options was last updated */ |
|
| 105 |
+#endif |
|
| 106 |
+ |
|
| 107 |
+ unsigned int flags; |
|
| 100 | 108 |
}; |
| 101 | 109 |
|
| 102 | 110 |
struct remote_entry |
| ... | ... |
@@ -114,6 +122,7 @@ struct connection_list |
| 114 | 114 |
{
|
| 115 | 115 |
int len; |
| 116 | 116 |
int current; |
| 117 |
+ int n_cycles; |
|
| 117 | 118 |
bool no_advance; |
| 118 | 119 |
struct connection_entry *array[CONNECTION_LIST_SIZE]; |
| 119 | 120 |
}; |
| ... | ... |
@@ -126,6 +135,14 @@ struct remote_list |
| 126 | 126 |
|
| 127 | 127 |
#endif |
| 128 | 128 |
|
| 129 |
+#if HTTP_PROXY_FALLBACK |
|
| 130 |
+struct hpo_store |
|
| 131 |
+{
|
|
| 132 |
+ struct http_proxy_options hpo; |
|
| 133 |
+ char server[80]; |
|
| 134 |
+}; |
|
| 135 |
+#endif |
|
| 136 |
+ |
|
| 129 | 137 |
/* Command line options */ |
| 130 | 138 |
struct options |
| 131 | 139 |
{
|
| ... | ... |
@@ -162,14 +179,22 @@ struct options |
| 162 | 162 |
struct connection_entry ce; |
| 163 | 163 |
|
| 164 | 164 |
#ifdef ENABLE_CONNECTION |
| 165 |
+ char *remote_ip_hint; |
|
| 165 | 166 |
struct connection_list *connection_list; |
| 166 | 167 |
struct remote_list *remote_list; |
| 168 |
+ bool force_connection_list; |
|
| 167 | 169 |
#endif |
| 168 | 170 |
|
| 169 | 171 |
#ifdef GENERAL_PROXY_SUPPORT |
| 170 | 172 |
struct auto_proxy_info *auto_proxy_info; |
| 171 | 173 |
#endif |
| 172 | 174 |
|
| 175 |
+#if HTTP_PROXY_FALLBACK |
|
| 176 |
+ bool http_proxy_fallback; |
|
| 177 |
+ struct http_proxy_options *http_proxy_override; |
|
| 178 |
+ struct hpo_store *hpo_store; /* used to store dynamic proxy info given by management interface */ |
|
| 179 |
+#endif |
|
| 180 |
+ |
|
| 173 | 181 |
bool remote_random; |
| 174 | 182 |
const char *ipchange; |
| 175 | 183 |
const char *dev; |
| ... | ... |
@@ -710,4 +735,15 @@ connection_list_set_no_advance (struct options *o) |
| 710 | 710 |
#endif |
| 711 | 711 |
} |
| 712 | 712 |
|
| 713 |
+#if HTTP_PROXY_FALLBACK |
|
| 714 |
+ |
|
| 715 |
+struct http_proxy_options * |
|
| 716 |
+parse_http_proxy_fallback (struct context *c, |
|
| 717 |
+ const char *server, |
|
| 718 |
+ const char *port, |
|
| 719 |
+ const char *flags, |
|
| 720 |
+ const int msglevel); |
|
| 721 |
+ |
|
| 722 |
+#endif /* HTTP_PROXY_FALLBACK */ |
|
| 723 |
+ |
|
| 713 | 724 |
#endif |
| ... | ... |
@@ -224,10 +224,14 @@ get_user_pass_http (struct http_proxy_info *p, const bool force) |
| 224 | 224 |
{
|
| 225 | 225 |
if (!static_proxy_user_pass.defined || force) |
| 226 | 226 |
{
|
| 227 |
+ unsigned int flags = GET_USER_PASS_MANAGEMENT; |
|
| 228 |
+ if (p->queried_creds) |
|
| 229 |
+ flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED; |
|
| 227 | 230 |
get_user_pass (&static_proxy_user_pass, |
| 228 | 231 |
p->options.auth_file, |
| 229 | 232 |
UP_TYPE_PROXY, |
| 230 |
- GET_USER_PASS_MANAGEMENT); |
|
| 233 |
+ flags); |
|
| 234 |
+ p->queried_creds = true; |
|
| 231 | 235 |
p->up = static_proxy_user_pass; |
| 232 | 236 |
} |
| 233 | 237 |
} |
| ... | ... |
@@ -755,12 +759,12 @@ establish_http_proxy_passthru (struct http_proxy_info *p, |
| 755 | 755 |
realm, |
| 756 | 756 |
password, |
| 757 | 757 |
nonce, |
| 758 |
- cnonce, |
|
| 758 |
+ (char *)cnonce, |
|
| 759 | 759 |
session_key); |
| 760 | 760 |
DigestCalcResponse(session_key, |
| 761 | 761 |
nonce, |
| 762 | 762 |
nonce_count, |
| 763 |
- cnonce, |
|
| 763 |
+ (char *)cnonce, |
|
| 764 | 764 |
qop, |
| 765 | 765 |
http_method, |
| 766 | 766 |
uri, |
| ... | ... |
@@ -877,6 +881,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p, |
| 877 | 877 |
goto error; |
| 878 | 878 |
} |
| 879 | 879 |
|
| 880 |
+ /* SUCCESS */ |
|
| 881 |
+ |
|
| 880 | 882 |
/* receive line from proxy and discard */ |
| 881 | 883 |
if (!recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received)) |
| 882 | 884 |
goto error; |
| ... | ... |
@@ -888,6 +894,9 @@ establish_http_proxy_passthru (struct http_proxy_info *p, |
| 888 | 888 |
while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received)) |
| 889 | 889 |
; |
| 890 | 890 |
|
| 891 |
+ /* reset queried_creds so that we don't think that the next creds request is due to an auth error */ |
|
| 892 |
+ p->queried_creds = false; |
|
| 893 |
+ |
|
| 891 | 894 |
#if 0 |
| 892 | 895 |
if (lookahead && BLEN (lookahead)) |
| 893 | 896 |
msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0)); |
| ... | ... |
@@ -71,7 +71,7 @@ struct http_proxy_options {
|
| 71 | 71 |
# define PAR_NO 0 /* don't support any auth retries */ |
| 72 | 72 |
# define PAR_ALL 1 /* allow all proxy auth protocols */ |
| 73 | 73 |
# define PAR_NCT 2 /* disable cleartext proxy auth protocols */ |
| 74 |
- bool auth_retry; |
|
| 74 |
+ int auth_retry; |
|
| 75 | 75 |
|
| 76 | 76 |
const char *auth_method_string; |
| 77 | 77 |
const char *auth_file; |
| ... | ... |
@@ -79,12 +79,19 @@ struct http_proxy_options {
|
| 79 | 79 |
const char *user_agent; |
| 80 | 80 |
}; |
| 81 | 81 |
|
| 82 |
+struct http_proxy_options_simple {
|
|
| 83 |
+ const char *server; |
|
| 84 |
+ int port; |
|
| 85 |
+ int auth_retry; |
|
| 86 |
+}; |
|
| 87 |
+ |
|
| 82 | 88 |
struct http_proxy_info {
|
| 83 | 89 |
bool defined; |
| 84 | 90 |
int auth_method; |
| 85 | 91 |
struct http_proxy_options options; |
| 86 | 92 |
struct user_pass up; |
| 87 | 93 |
char *proxy_authenticate; |
| 94 |
+ bool queried_creds; |
|
| 88 | 95 |
}; |
| 89 | 96 |
|
| 90 | 97 |
struct http_proxy_info *http_proxy_new (const struct http_proxy_options *o, |
| ... | ... |
@@ -625,6 +625,22 @@ socket_defined (const socket_descriptor_t sd) |
| 625 | 625 |
#define ENABLE_INLINE_FILES 1 |
| 626 | 626 |
|
| 627 | 627 |
/* |
| 628 |
+ * Support "connection" directive |
|
| 629 |
+ */ |
|
| 630 |
+#if ENABLE_INLINE_FILES |
|
| 631 |
+#define ENABLE_CONNECTION 1 |
|
| 632 |
+#endif |
|
| 633 |
+ |
|
| 634 |
+/* |
|
| 635 |
+ * Should we include http proxy fallback functionality |
|
| 636 |
+ */ |
|
| 637 |
+#if defined(ENABLE_CONNECTION) && defined(ENABLE_MANAGEMENT) && defined(ENABLE_HTTP_PROXY) |
|
| 638 |
+#define HTTP_PROXY_FALLBACK 1 |
|
| 639 |
+#else |
|
| 640 |
+#define HTTP_PROXY_FALLBACK 0 |
|
| 641 |
+#endif |
|
| 642 |
+ |
|
| 643 |
+/* |
|
| 628 | 644 |
* Reduce sensitivity to system clock instability |
| 629 | 645 |
* and backtracks. |
| 630 | 646 |
*/ |
| ... | ... |
@@ -646,11 +662,4 @@ socket_defined (const socket_descriptor_t sd) |
| 646 | 646 |
#define AUTO_USERID 0 |
| 647 | 647 |
#endif |
| 648 | 648 |
|
| 649 |
-/* |
|
| 650 |
- * Support "connection" directive |
|
| 651 |
- */ |
|
| 652 |
-#if ENABLE_INLINE_FILES |
|
| 653 |
-#define ENABLE_CONNECTION 1 |
|
| 654 |
-#endif |
|
| 655 |
- |
|
| 656 | 649 |
#endif |