git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5652 e7ae566f-a301-0410-adde-c780ea21d3b5
James Yonan authored on 2010/05/25 07:51:16... | ... |
@@ -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 |