Go to the documentation of this file.
43 #define UP_TYPE_PROXY "HTTP Proxy"
53 (*hpo)->http_version =
"1.0";
66 const int timeout_sec,
69 volatile int *signal_received)
95 tv.tv_sec = timeout_sec;
98 status = select(sd + 1, &reads, NULL, NULL, &tv);
101 if (*signal_received)
142 msg(
M_INFO,
"PROXY: read '%c' (%d)", c, (
int)c);
161 if (!isprint(c) && !isspace(c))
173 if (lastc ==
'\r' && c ==
'\n')
197 const ssize_t size = send(sd, buf, strlen(buf),
MSG_NOSIGNAL);
198 if (size != (ssize_t) strlen(buf))
296 volatile int *signal_received)
301 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true, NULL, signal_received))
319 volatile int *signal_received)
325 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true, NULL, signal_received))
336 if (ret ==
HTTP_AUTH_NONE && !strncmp(buf,
"Proxy-Authenticate: ", 20))
338 if (!strncmp(buf+20,
"Basic ", 6))
344 #if PROXY_DIGEST_AUTH
345 else if (!strncmp(buf+20,
"Digest ", 7))
353 else if (!strncmp(buf+20,
"NTLM", 4))
384 bool starts_with_quote =
false;
387 for (c = max_key_len-1; (*str && (*str !=
'=') && c--); )
403 starts_with_quote =
true;
406 for (c = max_value_len-1; *str && c--; str++)
422 if (!starts_with_quote)
438 if (!escape && starts_with_quote)
461 const char *content = pa;
483 while (*content && isspace(*content))
497 msg(
M_FATAL,
"HTTP_PROXY: server not specified");
520 msg(
M_INFO,
"NTLM v1 authentication is deprecated and will be removed in "
531 msg(
M_FATAL,
"ERROR: unknown HTTP authentication method: '%s'",
568 bool host_header_sent =
false;
584 host_header_sent =
true;
593 host_header_sent =
true;
597 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
604 if (!host_header_sent)
607 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
619 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
646 bool processed =
false;
671 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
693 msg(
D_PROXY,
"Attempting Basic Proxy-Authorization");
713 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 1");
741 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
744 nparms = sscanf(buf,
"%*s %d", &
status);
749 while (nparms >= 1 &&
status == 407)
751 msg(
D_PROXY,
"Proxy requires authentication");
769 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
771 openvpn_snprintf(get,
sizeof get,
"%%*s NTLM %%%ds", (
int)
sizeof(buf2) - 1);
772 nparms = sscanf(buf, get, buf2);
784 msg(
D_PROXY,
"Received NTLM Proxy-Authorization phase 2 response");
787 while (
recv_line(sd, NULL, 0, 2,
true, NULL, signal_received))
799 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
820 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 3");
825 msg(
D_PROXY,
"NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
831 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
852 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
855 nparms = sscanf(buf,
"%*s %d", &
status);
859 #if PROXY_DIGEST_AUTH
868 const char *http_method =
"CONNECT";
869 const char *nonce_count =
"00000001";
870 const char *qop =
"auth";
873 char *opaque_kv =
"";
875 uint8_t cnonce_raw[8];
880 const char *realm =
get_pa_var(
"realm", pa, &gc);
881 const char *nonce =
get_pa_var(
"nonce", pa, &gc);
882 const char *algor =
get_pa_var(
"algorithm", pa, &gc);
883 const char *opaque =
get_pa_var(
"opaque", pa, &gc);
885 if (!realm || !nonce)
888 "from server: realm= or nonce= missing" );
904 const int len = strlen(opaque)+16;
932 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
947 openvpn_snprintf(buf,
sizeof(buf),
"Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
958 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
977 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
980 nparms = sscanf(buf,
"%*s %d", &
status);
985 msg(
D_PROXY,
"HTTP proxy: digest method not supported");
1002 msg(
D_PROXY,
"HTTP proxy authenticate '%s'", pa);
1006 msg(
D_PROXY,
"HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
1017 msg(
D_PROXY,
"HTTP proxy: do not recognize the authentication method required by proxy");
1026 msg(
D_PROXY,
"HTTP proxy: no support for proxy authentication method");
1040 if (nparms < 1 ||
status != 200)
1062 while (
recv_line(sd, NULL, 0, 2,
false, lookahead, signal_received))
1070 if (lookahead &&
BLEN(lookahead))
volatile int signal_received
void DigestCalcResponse(IN HASHHEX HA1, IN char *pszNonce, IN char *pszNonceCount, IN char *pszCNonce, IN char *pszQop, IN char *pszMethod, IN char *pszDigestUri, IN HASHHEX HEntity, OUT HASHHEX Response)
uint8_t * make_base64_string2(const uint8_t *str, int src_len, struct gc_arena *gc)
static struct user_pass static_proxy_user_pass
#define GET_USER_PASS_PREVIOUS_CREDS_FAILED
static struct gc_arena gc_new(void)
static bool send_line_crlf(socket_descriptor_t sd, const char *src)
static int get_proxy_authenticate(socket_descriptor_t sd, int timeout, char **data, volatile int *signal_received)
const char * http_version
#define buf_init(buf, offset)
char username[USER_PASS_LEN]
const char * auth_method_string
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
static void get_user_pass_http(struct http_proxy_info *p, const bool force)
int openvpn_base64_encode(const void *data, int size, char **str)
struct http_proxy_options options
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
#define GET_USER_PASS_MANAGEMENT
Container for unidirectional cipher and HMAC key material.
bool establish_http_proxy_passthru(struct http_proxy_info *p, socket_descriptor_t sd, const char *host, const char *port, struct event_timeout *server_poll_timeout, struct buffer *lookahead, struct signal_info *sig_info)
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
char * string_alloc(const char *str, struct gc_arena *gc)
static void store_proxy_authenticate(struct http_proxy_info *p, char *data)
#define MAX_CUSTOM_HTTP_HEADER
void purge_user_pass(struct user_pass *up, const bool force)
static bool send_crlf(socket_descriptor_t sd)
static bool buf_write_u8(struct buffer *dest, uint8_t data)
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
static bool send_line(socket_descriptor_t sd, const char *buf)
Wrapper structure for dynamically allocated memory.
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
static bool buf_write(struct buffer *dest, const void *src, size_t size)
struct http_proxy_options * init_http_proxy_options_once(struct http_proxy_options **hpo, struct gc_arena *gc)
char * proxy_authenticate
Garbage collection arena used to keep track of dynamically allocated memory.
static bool recv_line(socket_descriptor_t sd, char *buf, int len, const int timeout_sec, const bool verbose, struct buffer *lookahead, volatile int *signal_received)
void free_buf(struct buffer *buf)
SOCKET socket_descriptor_t
static char * get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
static void clear_user_pass_http(void)
static const char * username_password_as_base64(const struct http_proxy_info *p, struct gc_arena *gc)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
const char * ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc)
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
static SERVICE_STATUS status
static void gc_free(struct gc_arena *a)
static bool add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, const char *host, const char *port)
#define ALLOC_OBJ_CLEAR(dptr, type)
static bool get_key_value(const char *str, char *key, char *value, int max_key_len, int max_value_len, const char **endptr)
static char * format_hex(const uint8_t *data, int size, int maxoutput, struct gc_arena *gc)
char password[USER_PASS_LEN]
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
#define GET_USER_PASS_INLINE_CREDS
const char * ntlm_phase_1(const struct http_proxy_info *p, struct gc_arena *gc)
uint8_t * make_base64_string(const uint8_t *str, struct gc_arena *gc)
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
struct buffer alloc_buf(size_t size)
struct http_proxy_info * http_proxy_new(const struct http_proxy_options *o)
struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER]
static bool buf_defined(const struct buffer *buf)
bool buf_printf(struct buffer *buf, const char *format,...)
void http_proxy_close(struct http_proxy_info *hp)
uint8_t * data
Pointer to the allocated memory.