26 #elif defined(_MSC_VER) 45 #define UP_TYPE_PROXY "HTTP Proxy" 55 (*hpo)->http_version =
"1.0";
68 const int timeout_sec,
71 volatile int *signal_received)
97 tv.tv_sec = timeout_sec;
100 status = select(sd + 1, &reads, NULL, NULL, &tv);
103 if (*signal_received)
144 msg(
M_INFO,
"PROXY: read '%c' (%d)", c, (
int)c);
163 if (!isprint(c) && !isspace(c))
175 if (lastc ==
'\r' && c ==
'\n')
200 if (size != (
ssize_t) strlen(buf))
298 volatile int *signal_received)
303 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true, NULL, signal_received))
321 volatile int *signal_received)
327 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true, NULL, signal_received))
338 if (ret ==
HTTP_AUTH_NONE && !strncmp(buf,
"Proxy-Authenticate: ", 20))
340 if (!strncmp(buf+20,
"Basic ", 6))
346 #if PROXY_DIGEST_AUTH 347 else if (!strncmp(buf+20,
"Digest ", 7))
355 else if (!strncmp(buf+20,
"NTLM", 4))
386 bool starts_with_quote =
false;
389 for (c = max_key_len-1; (*str && (*str !=
'=') && c--); )
405 starts_with_quote =
true;
408 for (c = max_value_len-1; *str && c--; str++)
424 if (!starts_with_quote)
440 if (!escape && starts_with_quote)
463 const char *content = pa;
485 while (*content && isspace(*content))
499 msg(
M_FATAL,
"HTTP_PROXY: server not specified");
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);
637 volatile int *signal_received)
646 bool processed =
false;
670 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
692 msg(
D_PROXY,
"Attempting Basic Proxy-Authorization");
712 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 1");
740 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
743 nparms = sscanf(buf,
"%*s %d", &status);
748 while (nparms >= 1 && status == 407)
750 msg(
D_PROXY,
"Proxy requires authentication");
768 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
770 openvpn_snprintf(
get,
sizeof get,
"%%*s NTLM %%%ds", (
int)
sizeof(buf2) - 1);
771 nparms = sscanf(buf,
get, buf2);
783 msg(
D_PROXY,
"Received NTLM Proxy-Authorization phase 2 response");
786 while (
recv_line(sd, NULL, 0, 2,
true, NULL, signal_received))
798 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
819 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 3");
824 msg(
D_PROXY,
"NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
830 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
851 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
854 nparms = sscanf(buf,
"%*s %d", &status);
858 #if PROXY_DIGEST_AUTH 867 const char *http_method =
"CONNECT";
868 const char *nonce_count =
"00000001";
869 const char *qop =
"auth";
872 char *opaque_kv =
"";
874 uint8_t cnonce_raw[8];
879 const char *realm =
get_pa_var(
"realm", pa, &gc);
880 const char *nonce =
get_pa_var(
"nonce", pa, &gc);
881 const char *algor =
get_pa_var(
"algorithm", pa, &gc);
882 const char *opaque =
get_pa_var(
"opaque", pa, &gc);
884 if (!realm || !nonce)
887 "from server: realm= or nonce= missing" );
903 const int len = strlen(opaque)+16;
931 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
946 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",
957 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
976 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
979 nparms = sscanf(buf,
"%*s %d", &status);
984 msg(
D_PROXY,
"HTTP proxy: digest method not supported");
1001 msg(
D_PROXY,
"HTTP proxy authenticate '%s'", pa);
1005 msg(
D_PROXY,
"HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
1016 msg(
D_PROXY,
"HTTP proxy: do not recognize the authentication method required by proxy");
1025 msg(
D_PROXY,
"HTTP proxy: no support for proxy authentication method");
1039 if (nparms < 1 || status != 200)
1061 while (
recv_line(sd, NULL, 0, 2,
false, lookahead, signal_received))
1069 if (lookahead &&
BLEN(lookahead))
1080 if (!*signal_received)
static bool buf_write_u8(struct buffer *dest, int data)
struct http_proxy_info * http_proxy_new(const struct http_proxy_options *o)
const char * http_version
void free_buf(struct buffer *buf)
char * string_alloc(const char *str, struct gc_arena *gc)
static bool get_key_value(const char *str, char *key, char *value, int max_key_len, int max_value_len, const char **endptr)
static void gc_free(struct gc_arena *a)
const char * ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc)
#define GET_USER_PASS_INLINE_CREDS
static char * get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
void http_proxy_close(struct http_proxy_info *hp)
struct buffer alloc_buf(size_t size)
struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER]
bool buf_printf(struct buffer *buf, const char *format,...)
static char * format_hex(const uint8_t *data, int size, int maxoutput, struct gc_arena *gc)
static void get_signal(volatile int *sig)
const char * ntlm_phase_1(const struct http_proxy_info *p, struct gc_arena *gc)
static void clear_user_pass_http(void)
char username[USER_PASS_LEN]
const char * auth_method_string
static struct user_pass static_proxy_user_pass
struct http_proxy_options * init_http_proxy_options_once(struct http_proxy_options **hpo, struct gc_arena *gc)
#define GET_USER_PASS_PREVIOUS_CREDS_FAILED
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
uint8_t * make_base64_string(const uint8_t *str, struct gc_arena *gc)
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
static struct gc_arena gc_new(void)
#define ALLOC_OBJ_CLEAR(dptr, type)
static const char * username_password_as_base64(const struct http_proxy_info *p, struct gc_arena *gc)
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
static void get_user_pass_http(struct http_proxy_info *p, const bool force)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
uint8_t * make_base64_string2(const uint8_t *str, int src_len, struct gc_arena *gc)
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
Interface functions to the internal and external multiplexers.
int openvpn_base64_encode(const void *data, int size, char **str)
uint8_t * data
Pointer to the allocated memory.
static void store_proxy_authenticate(struct http_proxy_info *p, char *data)
#define MAX_CUSTOM_HTTP_HEADER
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
static bool buf_defined(const struct buffer *buf)
char * proxy_authenticate
void purge_user_pass(struct user_pass *up, const bool force)
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
SOCKET socket_descriptor_t
static bool add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, const char *host, const char *port)
Wrapper structure for dynamically allocated memory.
#define buf_init(buf, offset)
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)
static int get_proxy_authenticate(socket_descriptor_t sd, int timeout, char **data, volatile int *signal_received)
static bool send_line(socket_descriptor_t sd, const char *buf)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
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, volatile int *signal_received)
Garbage collection arena used to keep track of dynamically allocated memory.
static bool buf_write(struct buffer *dest, const void *src, size_t size)
static bool send_line_crlf(socket_descriptor_t sd, const char *src)
char password[USER_PASS_LEN]
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)
static SERVICE_STATUS status
struct http_proxy_options options
static bool send_crlf(socket_descriptor_t sd)
Container for unidirectional cipher and HMAC key material.
#define GET_USER_PASS_MANAGEMENT