42#define UP_TYPE_PROXY "HTTP Proxy"
51 (*hpo)->http_version =
"1.0";
57#if defined(__GNUC__) || defined(__clang__)
58#pragma GCC diagnostic push
59#pragma GCC diagnostic ignored "-Wconversion"
67 struct buffer *lookahead,
volatile int *signal_received)
93 tv.tv_sec = timeout_sec;
96 status = select(sd + 1, &reads, NULL, NULL, &tv);
140 msg(
M_INFO,
"PROXY: read '%c' (%d)", c, (
int)c);
159 if (!isprint(c) && !isspace(c))
164 "recv_line: Non-ASCII character (%d) read on recv()", (
int)c);
172 if (lastc ==
'\r' && c ==
'\n')
195 const ssize_t size = send(sd, buf, strlen(buf),
MSG_NOSIGNAL);
196 if (size != (ssize_t)strlen(buf))
245 buf_printf(&out,
"%s:%s",
p->up.username,
p->up.password);
272 const char *auth_file =
p->options.auth_file;
273 if (
p->options.auth_file_up)
275 auth_file =
p->options.auth_file_up;
281 if (
p->options.inline_creds)
293 p->queried_creds =
true;
302 volatile int *signal_received)
307 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true,
NULL, signal_received))
323 volatile int *signal_received)
329 if (!
recv_line(sd, buf,
sizeof(buf), timeout,
true,
NULL, signal_received))
342 if (!
strncmp(buf + 20,
"Basic ", 6))
349 else if (!
strncmp(buf + 20,
"Digest ", 7))
357 else if (!
strncmp(buf + 20,
"NTLM", 4))
371 free(
p->proxy_authenticate);
372 p->proxy_authenticate =
data;
463 const char *content =
pa;
485 while (*content &&
isspace(*content))
499 msg(
M_FATAL,
"HTTP_PROXY: server not specified");
523 "NTLM v1 authentication has been removed in OpenVPN 2.7. Will try to use NTLM v2 authentication.");
549 "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");
570 bool host_header_sent =
false;
585 host_header_sent =
true;
593 host_header_sent =
true;
597 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
604 if (!host_header_sent)
606 snprintf(buf,
sizeof(buf),
"Host: %s", host);
607 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
618 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
642 bool processed =
false;
670 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
690 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: Basic %s",
692 msg(
D_PROXY,
"Attempting Basic Proxy-Authorization");
703 snprintf(buf,
sizeof(buf),
"Proxy-Connection: Keep-Alive");
709 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: NTLM %s",
ntlm_phase_1(p, &
gc));
710 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 1");
734 true, NULL, signal_received))
742 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
745 nparms = sscanf(buf,
"%*s %d", &
status);
749 while (nparms >= 1 &&
status == 407)
751 msg(
D_PROXY,
"Proxy requires authentication");
771 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
775 snprintf(get,
sizeof(get),
"%%*s NTLM %%%zus",
sizeof(buf2) - 1);
776 nparms = sscanf(buf, get, buf2);
787 msg(
D_PROXY,
"Received NTLM Proxy-Authorization phase 2 response");
790 while (
recv_line(sd, NULL, 0, 2,
true, NULL, signal_received))
797 snprintf(buf,
sizeof(buf),
"CONNECT %s:%s HTTP/%s", host, port,
800 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
809 snprintf(buf,
sizeof(buf),
"Proxy-Connection: Keep-Alive");
821 msg(
D_PROXY,
"Attempting NTLM Proxy-Authorization phase 3");
827 "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
830 snprintf(buf,
sizeof(buf),
"Proxy-Authorization: NTLM %s", np3);
833 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
856 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
859 nparms = sscanf(buf,
"%*s %d", &
status);
872 const char *http_method =
"CONNECT";
873 const char *nonce_count =
"00000001";
874 const char *qop =
"auth";
877 char *opaque_kv =
"";
879 uint8_t cnonce_raw[8];
889 if (!realm || !nonce)
892 "from server: realm= or nonce= missing");
902 snprintf(uri,
sizeof(uri),
"%s:%s", host, port);
906 const int len = strlen(opaque) + 16;
908 snprintf(opaque_kv, len,
", opaque=\"%s\"", opaque);
911 DigestCalcHA1(algor, username, realm, password, nonce, (
char *)cnonce, session_key);
913 http_method, uri, NULL, response);
916 snprintf(buf,
sizeof(buf),
"%s %s HTTP/%s", http_method, uri,
919 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
936 "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
937 username, realm, nonce, uri, qop, nonce_count, cnonce, response, opaque_kv);
938 if (sret >=
sizeof(buf))
943 msg(
D_PROXY,
"Send to HTTP proxy: '%s'", buf);
966 msg(
D_PROXY,
"HTTP proxy returned: '%s'", buf);
969 nparms = sscanf(buf,
"%*s %d", &
status);
974 msg(
D_PROXY,
"HTTP proxy: digest method not supported");
989 msg(
D_PROXY,
"HTTP proxy authenticate '%s'", pa);
994 "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
1006 "HTTP proxy: do not recognize the authentication method required by proxy");
1015 msg(
D_PROXY,
"HTTP proxy: no support for proxy authentication method");
1022 if (nparms < 1 ||
status != 200)
1045 while (
recv_line(sd, NULL, 0, 2,
false, lookahead, signal_received))
1054 if (lookahead &&
BLEN(lookahead))
1072#if defined(__GNUC__) || defined(__clang__)
1073#pragma GCC diagnostic pop
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
indicates that auth_file is actually 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