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))
249 buf_printf(&out,
"%s:%s",
p->up.username,
p->up.password);
276 const char *auth_file =
p->options.auth_file;
277 if (
p->options.auth_file_up)
279 auth_file =
p->options.auth_file_up;
285 if (
p->options.inline_creds)
300 p->queried_creds =
true;
309 volatile int *signal_received)
314 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true,
NULL, signal_received))
332 volatile int *signal_received)
338 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true,
NULL, signal_received))
351 if (!
strncmp(buf+20,
"Basic ", 6))
358 else if (!
strncmp(buf+20,
"Digest ", 7))
366 else if (!
strncmp(buf+20,
"NTLM", 4))
380 free(
p->proxy_authenticate);
381 p->proxy_authenticate =
data;
474 const char *content =
pa;
496 while (*content &&
isspace(*content))
510 msg(
M_FATAL,
"HTTP_PROXY: server not specified");
533 msg(
M_WARN,
"NTLM v1 authentication has been removed in OpenVPN 2.7. Will try to use NTLM v2 authentication.");
543 msg(
M_FATAL,
"ERROR: unknown HTTP authentication method: '%s'",
559 msg(
M_FATAL,
"Sorry, this version of " PACKAGE_NAME
" was built without NTLM Proxy support.");
581 bool host_header_sent =
false;
592 snprintf(buf,
sizeof(buf),
"%s: %s",
597 host_header_sent =
true;
602 snprintf(buf,
sizeof(buf),
"%s",
606 host_header_sent =
true;
610 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
617 if (!host_header_sent)
619 snprintf(buf,
sizeof(buf),
"Host: %s", host);
620 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
630 snprintf(buf,
sizeof(buf),
"User-Agent: %s",
632 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
657 bool processed =
false;
683 snprintf(buf,
sizeof(buf),
"CONNECT %s:%s HTTP/%s",
688 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
708 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: Basic %s",
710 msg(
D_PROXY,
"Attempting Basic Proxy-Authorization");
721 snprintf(buf,
sizeof(buf),
"Proxy-Connection: Keep-Alive");
727 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: NTLM %s",
729 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 1");
760 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
763 nparms = sscanf(buf,
"%*s %d", &
status);
768 while (nparms >= 1 &&
status == 407)
770 msg(
D_PROXY,
"Proxy requires authentication");
788 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
792 snprintf(get,
sizeof(get),
"%%*s NTLM %%%zus",
sizeof(buf2) - 1);
793 nparms = sscanf(buf, get, buf2);
804 msg(
D_PROXY,
"Received NTLM Proxy-Authorization phase 2 response");
807 while (
recv_line(sd, NULL, 0, 2,
true, NULL, signal_received))
814 snprintf(buf,
sizeof(buf),
"CONNECT %s:%s HTTP/%s",
819 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
828 snprintf(buf,
sizeof(buf),
"Proxy-Connection: Keep-Alive");
840 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 3");
845 msg(
D_PROXY,
"NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
848 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: NTLM %s", np3);
851 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
872 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
875 nparms = sscanf(buf,
"%*s %d", &
status);
888 const char *http_method =
"CONNECT";
889 const char *nonce_count =
"00000001";
890 const char *qop =
"auth";
893 char *opaque_kv =
"";
895 uint8_t cnonce_raw[8];
905 if (!realm || !nonce)
908 "from server: realm= or nonce= missing" );
918 snprintf(uri,
sizeof(uri),
"%s:%s",
924 const int len = strlen(opaque)+16;
926 snprintf(opaque_kv, len,
", opaque=\"%s\"", opaque);
947 snprintf(buf,
sizeof(buf),
"%s %s HTTP/%s",
952 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
967 int sret = snprintf(buf,
sizeof(buf),
"Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
978 if (sret >=
sizeof(buf))
983 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
1004 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
1007 nparms = sscanf(buf,
"%*s %d", &
status);
1012 msg(
D_PROXY,
"HTTP proxy: digest method not supported");
1029 msg(
D_PROXY,
"HTTP proxy authenticate '%s'", pa);
1033 msg(
D_PROXY,
"HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
1044 msg(
D_PROXY,
"HTTP proxy: do not recognize the authentication method required by proxy");
1053 msg(
D_PROXY,
"HTTP proxy: no support for proxy authentication method");
1060 if (nparms < 1 ||
status != 200)
1082 while (
recv_line(sd, NULL, 0, 2,
false, lookahead, signal_received))
1090 if (lookahead &&
BLEN(lookahead))
void free_buf(struct buffer *buf)
bool buf_printf(struct buffer *buf, const char *format,...)
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
struct buffer alloc_buf(size_t size)
char * string_alloc(const char *str, struct gc_arena *gc)
static char * format_hex(const uint8_t *data, int size, int maxoutput, struct gc_arena *gc)
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
static bool buf_write(struct buffer *dest, const void *src, size_t size)
static bool buf_write_u8(struct buffer *dest, uint8_t data)
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
static void gc_free(struct gc_arena *a)
#define ALLOC_OBJ_CLEAR(dptr, type)
static bool buf_defined(const struct buffer *buf)
#define buf_init(buf, offset)
static struct gc_arena gc_new(void)
Data Channel Cryptography Module.
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
Interface functions to the internal and external multiplexers.
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
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
void unprotect_user_pass(struct user_pass *up)
Decrypt username and password buffers in user_pass.
void purge_user_pass(struct user_pass *up, const bool force)
void protect_user_pass(struct user_pass *up)
Encrypt username and password buffers in user_pass.
#define GET_USER_PASS_MANAGEMENT
#define GET_USER_PASS_INLINE_CREDS
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
Retrieves the user credentials from various sources depending on the flags.
#define GET_USER_PASS_PREVIOUS_CREDS_FAILED
const char * ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc)
const char * ntlm_phase_1(const struct http_proxy_info *p, struct gc_arena *gc)
static bool send_crlf(socket_descriptor_t sd)
static struct user_pass static_proxy_user_pass
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 http_proxy_close(struct http_proxy_info *hp)
static void clear_user_pass_http(void)
static char * get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
static const char * username_password_as_base64(const struct http_proxy_info *p, struct gc_arena *gc)
struct http_proxy_info * http_proxy_new(const struct http_proxy_options *o)
struct http_proxy_options * init_http_proxy_options_once(struct http_proxy_options **hpo, struct gc_arena *gc)
static void store_proxy_authenticate(struct http_proxy_info *p, char *data)
static bool get_key_value(const char *str, char *key, char *value, int max_key_len, int max_value_len, const char **endptr)
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)
static bool send_line(socket_descriptor_t sd, const char *buf)
static bool send_line_crlf(socket_descriptor_t sd, const char *src)
static void get_user_pass_http(struct http_proxy_info *p, const bool force)
uint8_t * make_base64_string2(const uint8_t *str, int src_len, struct gc_arena *gc)
uint8_t * make_base64_string(const uint8_t *str, struct gc_arena *gc)
static bool add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, const char *host)
static int get_proxy_authenticate(socket_descriptor_t sd, int timeout, char **data, volatile int *signal_received)
#define MAX_CUSTOM_HTTP_HEADER
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.
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
int openvpn_base64_encode(const void *data, int size, char **str)
Wrapper structure for dynamically allocated memory.
uint8_t * data
Pointer to the allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
char * proxy_authenticate
struct http_proxy_options options
const char * http_version
const char * auth_method_string
struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER]
Container for unidirectional cipher and HMAC key material.
volatile int signal_received
char password[USER_PASS_LEN]
char username[USER_PASS_LEN]
SOCKET socket_descriptor_t