diff --git a/lib/client-handshake.c b/lib/client-handshake.c index f8fd6de0..cd93a0b9 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -27,11 +27,18 @@ struct libwebsocket *libwebsocket_client_connect_2( if (context->http_proxy_port) { plen = sprintf((char *)context->service_buffer, "CONNECT %s:%u HTTP/1.0\x0d\x0a" - "User-agent: libwebsockets\x0d\x0a" -/*Proxy-authorization: basic aGVsbG86d29ybGQ= */ - "\x0d\x0a", + "User-agent: libwebsockets\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS), wsi->u.hdr.ah->c_port); + + if (context->proxy_basic_auth_token) + plen += sprintf((char *)context->service_buffer + plen, + "Proxy-authorization: basic %s\x0d\x0a", + context->proxy_basic_auth_token); + + plen += sprintf((char *)context->service_buffer + plen, + "\x0d\x0a"); + ads = context->http_proxy_address; #ifdef LWS_USE_IPV6 @@ -54,7 +61,7 @@ struct libwebsocket *libwebsocket_client_connect_2( /* * prepare the actual connection (to the proxy, if any) */ - lwsl_client("libwebsocket_client_connect_2: address %s\n", ads); + lwsl_client("%s: address %s\n", __func__, ads); #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { diff --git a/lib/context.c b/lib/context.c index 385561d2..98c9ea20 100644 --- a/lib/context.c +++ b/lib/context.c @@ -176,39 +176,21 @@ libwebsocket_create_context(struct lws_context_creation_info *info) lws_server_get_canonical_hostname(context, info); - /* split the proxy ads:port if given */ + /* either use proxy from info, or try get it from env var */ if (info->http_proxy_address) { - strncpy(context->http_proxy_address, info->http_proxy_address, - sizeof(context->http_proxy_address) - 1); - context->http_proxy_address[ - sizeof(context->http_proxy_address) - 1] = '\0'; - context->http_proxy_port = info->http_proxy_port; + /* override for backwards compatibility */ + if (info->http_proxy_port) + context->http_proxy_port = info->http_proxy_port; + libwebsocket_set_proxy(context, info->http_proxy_address); } else { #ifdef LWS_HAVE_GETENV p = getenv("http_proxy"); - if (p) { - strncpy(context->http_proxy_address, p, - sizeof(context->http_proxy_address) - 1); - context->http_proxy_address[ - sizeof(context->http_proxy_address) - 1] = '\0'; - - p = strchr(context->http_proxy_address, ':'); - if (p == NULL) { - lwsl_err("http_proxy needs to be ads:port\n"); - goto bail; - } - *p = '\0'; - context->http_proxy_port = atoi(p + 1); - } + if (p) + libwebsocket_set_proxy(context, p); #endif } - if (context->http_proxy_address[0]) - lwsl_notice(" Proxy %s:%u\n", - context->http_proxy_address, - context->http_proxy_port); - lwsl_notice( " per-conn mem: %u + %u headers + protocol rx buf\n", sizeof(struct libwebsocket), diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index e680481e..d1ab6194 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -672,28 +672,54 @@ LWS_VISIBLE int libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy) { char *p; + char authstring[96]; if (!proxy) return -1; + p = strchr(proxy, '@'); + if (p) { /* auth is around */ + + if ((p - proxy) > sizeof(authstring) - 1) + goto auth_too_long; + + strncpy(authstring + 6, proxy, p - proxy); + // null termination not needed on input + if (lws_b64_encode_string(authstring, (p - proxy), + context->proxy_basic_auth_token, + sizeof context->proxy_basic_auth_token) < 0) + goto auth_too_long; + + lwsl_notice(" Proxy auth in use\n"); + + proxy = p + 1; + } else + context->proxy_basic_auth_token[0] = '\0'; + strncpy(context->http_proxy_address, proxy, sizeof(context->http_proxy_address) - 1); context->http_proxy_address[ sizeof(context->http_proxy_address) - 1] = '\0'; - + p = strchr(context->http_proxy_address, ':'); - if (!p) { + if (!p && !context->http_proxy_port) { lwsl_err("http_proxy needs to be ads:port\n"); return -1; + } else { + *p = '\0'; + context->http_proxy_port = atoi(p + 1); } - *p = '\0'; - context->http_proxy_port = atoi(p + 1); - + lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address, context->http_proxy_port); return 0; + +auth_too_long: + lwsl_err("proxy auth too long\n"); + + return -1; } /** diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 859ee965..3d7b4690 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1047,7 +1047,9 @@ struct libwebsocket_extension { * @ssl_cipher_list: List of valid ciphers to use (eg, * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" * or you can leave it as NULL to get "DEFAULT" - * @http_proxy_address: If non-NULL, attempts to proxy via the given address + * @http_proxy_address: If non-NULL, attempts to proxy via the given address. + * If proxy auth is required, use format + * "username:password@server:port" * @http_proxy_port: If http_proxy_address was non-NULL, uses this port at the address * @gid: group id to change to after setting listen socket, or -1. * @uid: user id to change to after setting listen socket, or -1. diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index da6a2d9d..a96e2952 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -452,6 +452,7 @@ struct libwebsocket_context { const char *iface; char http_proxy_address[128]; char canonical_hostname[128]; + char proxy_basic_auth_token[128]; unsigned int http_proxy_port; unsigned int options; time_t last_timeout_check_s;