Ver código fonte

http_client Adding support for HTTP proxy on a connection and default level

Addresses issue #541

Documentation coming in separate commit
Olle E. Johansson 9 anos atrás
pai
commit
876648a15a

+ 50 - 16
modules/http_client/curlcon.c

@@ -58,6 +58,8 @@ typedef struct raw_http_client_conn
 	str clientcert;
 	str clientkey;
 	str ciphersuites;
+	str http_proxy;
+	int http_proxy_port;
 	int verify_peer;
 	int verify_host;
 	int tlsversion;
@@ -82,20 +84,22 @@ static cfg_option_t tls_versions[] = {
 };
 
 static cfg_option_t http_client_options[] = {
-	{"url",                  .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"username",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"password",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"failover",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"useragent",            .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"verify_peer",          .f = cfg_parse_bool_opt},
-	{"verify_host",          .f = cfg_parse_bool_opt},
-	{"client_cert",          .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"client_key",           .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"cipher_suites",        .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
-	{"tlsversion",           .f = cfg_parse_enum_opt, .param = tls_versions},
-	{"timeout",              .f = cfg_parse_int_opt},
-	{"maxdatasize",          .f = cfg_parse_int_opt},
-	{"httpredirect",         .f = cfg_parse_bool_opt},
+	{"url",                  .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 0 */
+	{"username",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 1 */
+	{"password",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 2 */
+	{"failover",             .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 3 */
+	{"useragent",            .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 4 */
+	{"verify_peer",          .f = cfg_parse_bool_opt},	/* 5 */
+	{"verify_host",          .f = cfg_parse_bool_opt},	/* 6 */
+	{"client_cert",          .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 7 */
+	{"client_key",           .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 8 */
+	{"cipher_suites",        .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 9 */
+	{"tlsversion",           .f = cfg_parse_enum_opt, .param = tls_versions},	/* 10 */
+	{"timeout",              .f = cfg_parse_int_opt},	/* 11 */
+	{"maxdatasize",          .f = cfg_parse_int_opt},	/* 12 */
+	{"httpredirect",         .f = cfg_parse_bool_opt},	/* 13 */
+	{"httpproxy",           .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},	/* 14 */
+	{"httpproxyport",      .f = cfg_parse_int_opt},	/* 15 */
 	{0}
 };
 
@@ -171,7 +175,9 @@ int curl_parse_param(char *val)
 	str client_key   = default_tls_clientkey;
 	str ciphersuites = default_cipher_suite_list;
 	str useragent    = default_useragent;
+	str http_proxy   = default_http_proxy;
 
+	unsigned int http_proxy_port = default_http_proxy_port;
 	unsigned int maxdatasize = default_maxdatasize;
 	unsigned int timeout	= default_connection_timeout;
 	unsigned int http_follow_redirect = default_http_follow_redirect;
@@ -185,8 +191,9 @@ int curl_parse_param(char *val)
 	param_t *conparams = NULL;
 	curl_con_t *cc = NULL;
 
-	LM_INFO("curl modparam parsing starting\n");
+	LM_INFO("http_client modparam parsing starting\n");
 	LM_DBG("modparam httpcon: %s\n", val);
+	LM_DBG(" *** Default httproxy: %s\n", http_proxy.s);
 
 	/* parse: name=>http_url*/
 	in.s = val;
@@ -436,6 +443,11 @@ int curl_parse_param(char *val)
 	cc->verify_host = verify_host;
 	cc->timeout = timeout;
 	cc->maxdatasize = maxdatasize;
+	if (http_proxy_port > 0) {
+		cc->http_proxy_port = http_proxy_port;
+		cc->http_proxy = http_proxy.s ? as_asciiz(&http_proxy) : NULL;
+		LM_DBG("*** Setting HTTP proxy for connection to %s \n", cc->http_proxy);
+	}
 	cc->http_follow_redirect = http_follow_redirect;
 
 	LM_DBG("cname: [%.*s] url: [%.*s] username [%s] password [%s] failover [%.*s] timeout [%d] useragent [%s] maxdatasize [%d]\n", 
@@ -443,6 +455,10 @@ int curl_parse_param(char *val)
 			cc->failover.len, cc->failover.s, cc->timeout, cc->useragent, cc->maxdatasize);
 	LM_DBG("cname: [%.*s] client_cert [%s] client_key [%s] ciphersuites [%s] tlsversion [%d] verify_peer [%d] verify_host [%d]\n",
 			cc->name.len, cc->name.s, cc->clientcert, cc->clientkey, cc->ciphersuites, cc->tlsversion, cc->verify_peer, cc->verify_host);
+	if (cc->http_proxy_port > 0) {
+		LM_DBG("cname: [%.*s] http_proxy [%s] http_proxy_port [%d]\n",
+		cc->name.len, cc->name.s, cc->http_proxy, cc->http_proxy_port);
+	}
 
 	return 0;
 
@@ -501,6 +517,12 @@ int curl_parse_conn(void *param, cfg_parser_t *parser, unsigned int flags)
 	if (default_cipher_suite_list.s != NULL)
 		pkg_str_dup(&raw_cc->ciphersuites, &default_cipher_suite_list);
 	pkg_str_dup(&raw_cc->useragent,    &default_useragent);
+	if (default_http_proxy_port > 0) {
+		raw_cc->http_proxy_port = default_http_proxy_port;
+		if (default_http_proxy.s != NULL) {
+			pkg_str_dup(&raw_cc->http_proxy,   &default_http_proxy);
+		}
+	}
 	raw_cc->verify_peer = default_tls_verify_peer;
 	raw_cc->verify_host = default_tls_verify_host;
 	raw_cc->maxdatasize = default_maxdatasize;
@@ -511,6 +533,7 @@ int curl_parse_conn(void *param, cfg_parser_t *parser, unsigned int flags)
 	for(i = 0; tls_versions[i].name; i++) {
 		tls_versions[i].param = &raw_cc->tlsversion;
 	}
+	/* Index from above structure (see top of file) */
 	http_client_options[0].param = &raw_cc->url;
 	http_client_options[1].param = &raw_cc->username;
 	http_client_options[2].param = &raw_cc->password;
@@ -525,7 +548,8 @@ int curl_parse_conn(void *param, cfg_parser_t *parser, unsigned int flags)
 	http_client_options[11].param = &raw_cc->timeout;
 	http_client_options[12].param = &raw_cc->maxdatasize;
 	http_client_options[13].param = &raw_cc->http_follow_redirect;
-
+	http_client_options[14].param = &raw_cc->http_proxy;
+	http_client_options[15].param = &raw_cc->http_proxy_port;
 
 	cfg_set_options(parser, http_client_options);
 
@@ -583,6 +607,11 @@ int fixup_raw_http_client_conn_list(void)
 			LM_WARN("curl connection [%.*s]: tlsversion %d unsupported value. Using default\n", cc->name.len, cc->name.s, cc->tlsversion);
 			cc->tlsversion = default_tls_version;
 		}
+		cc->http_proxy_port = raw_cc->http_proxy_port;
+		if (cc->http_proxy_port > 0 && raw_cc->http_proxy.s != NULL) {
+			cc->http_proxy = raw_cc->http_proxy.s ? as_asciiz(&raw_cc->http_proxy) : NULL;
+		}
+
 		cc->verify_peer = raw_cc->verify_peer;
 		cc->verify_host = raw_cc->verify_host;
 		cc->timeout = raw_cc->timeout;
@@ -594,6 +623,10 @@ int fixup_raw_http_client_conn_list(void)
 			cc->failover.len, cc->failover.s, cc->timeout, cc->useragent, cc->maxdatasize);
 		LM_DBG("cname: [%.*s] client_cert [%s] client_key [%s] ciphersuites [%s] tlsversion [%d] verify_peer [%d] verify_host [%d]\n",
 			cc->name.len, cc->name.s, cc->clientcert, cc->clientkey, cc->ciphersuites, cc->tlsversion, cc->verify_peer, cc->verify_host);
+		if (cc->http_proxy_port > 0) {
+			LM_DBG("cname: [%.*s] http_proxy [%s] http_proxy_port [%d]\n",
+			cc->name.len, cc->name.s, cc->http_proxy, cc->http_proxy_port);
+		}
 
 	}
 done:
@@ -609,6 +642,7 @@ done:
 		if (raw_cc->clientcert.s) pkg_free(raw_cc->clientcert.s);
 		if (raw_cc->clientkey.s) pkg_free(raw_cc->clientkey.s);
 		if (raw_cc->ciphersuites.s) pkg_free(raw_cc->ciphersuites.s);
+		if (raw_cc->http_proxy.s) pkg_free(raw_cc->http_proxy.s);
 		pkg_free(raw_cc);
 		raw_conn_list = raw_conn_list->next;
 	}

+ 14 - 0
modules/http_client/functions.c

@@ -55,6 +55,8 @@ typedef struct {
     char *clientkey;
     char *cacert;
     char *ciphersuites;
+    char *http_proxy;
+    unsigned int http_proxy_port;
     unsigned int tlsversion;
     unsigned int verify_peer;
     unsigned int verify_host;
@@ -180,6 +182,15 @@ static int curL_query_url(struct sip_msg* _m, const char* _url, str* _dst, const
         res |= curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, params->ciphersuites);
     }
 
+    if (params->http_proxy  != NULL) {
+	res |= curl_easy_setopt(curl, CURLOPT_PROXY, params->http_proxy);
+    }
+
+    if (params->http_proxy_port > 0) {
+	res |= curl_easy_setopt(curl, CURLOPT_PROXYPORT, params->http_proxy_port);
+    }
+
+
     res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) params->verify_peer);
     res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long) params->verify_host?2:0);
 
@@ -191,6 +202,7 @@ static int curL_query_url(struct sip_msg* _m, const char* _url, str* _dst, const
     res |= curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
     res |= curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);
 
+
     if (res != CURLE_OK) {
 	/* PANIC */
 	LM_ERR("Could not set CURL options. Library error \n");
@@ -366,6 +378,8 @@ int curl_con_query_url(struct sip_msg* _m, const str *connection, const str* url
 	query_params.http_follow_redirect = conn->http_follow_redirect;
 	query_params.oneline = 0;
 	query_params.maxdatasize = maxdatasize;
+	query_params.http_proxy_port = conn->http_proxy_port;
+	query_params.http_proxy = conn->http_proxy;
 
 	res = curL_query_url(_m, urlbuf, result, &query_params);
 

+ 4 - 4
modules/http_client/http_client.c

@@ -80,7 +80,7 @@ str		default_cipher_suite_list = STR_NULL;		/*!< List of allowed cipher suites *
 unsigned int	default_tls_version = 0;		/*!< 0 = Use libcurl default */
 unsigned int	default_tls_verify_peer = 1;		/*!< 0 = Do not verify TLS server cert. 1 = Verify TLS cert (default) */
 unsigned int	default_tls_verify_host = 2;		/*!< 0 = Do not verify TLS server CN/SAN  2 = Verify TLS server CN/SAN (default) */
-char 		*default_http_proxy = NULL;		/*!< Default HTTP proxy to use */
+str 		default_http_proxy = STR_NULL;		/*!< Default HTTP proxy to use */
 unsigned int	default_http_proxy_port = 0;		/*!< Default HTTP proxy port to use */
 unsigned int	default_http_follow_redirect = 0;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
 str 		default_useragent = { CURL_USER_AGENT, CURL_USER_AGENT_LEN };	/*!< Default CURL useragent. Default "Kamailio Curl " */
@@ -140,7 +140,6 @@ static cmd_export_t cmds[] = {
 /* Exported parameters */
 static param_export_t params[] = {
     	{"connection_timeout", PARAM_INT, &default_connection_timeout},
-	{"httpcon",  PARAM_STRING|USE_FUNC_PARAM, (void*)curl_con_param},
 	{"cacert", PARAM_STRING,  &default_tls_cacert },
 	{"client_cert", PARAM_STR, &default_tls_clientcert },
 	{"client_key", PARAM_STR, &default_tls_clientkey },
@@ -149,11 +148,12 @@ static param_export_t params[] = {
 	{"verify_peer", PARAM_INT, &default_tls_verify_peer },
 	{"verify_host", PARAM_INT, &default_tls_verify_host },
 	{"httpproxyport", PARAM_INT, &default_http_proxy_port },
-	{"httpproxy", PARAM_STRING, &default_http_proxy},
+	{"httpproxy", PARAM_STR, &default_http_proxy},
 	{"httpredirect", PARAM_INT, &default_http_follow_redirect },
 	{"useragent", PARAM_STR,  &default_useragent },
 	{"maxdatasize", PARAM_INT,  &default_maxdatasize },
 	{"config_file", PARAM_STR,  &http_client_config_file },
+	{"httpcon",  PARAM_STRING|USE_FUNC_PARAM, (void*)curl_con_param},
     	{0, 0, 0}
 };
 
@@ -271,7 +271,7 @@ static int mod_init(void)
 	LM_DBG("**** init curl: Cipher Suites: %.*s \n", default_cipher_suite_list.len, default_cipher_suite_list.s);
 	LM_DBG("**** init curl: SSL Version: %d \n", default_tls_version);
 	LM_DBG("**** init curl: verifypeer: %d verifyhost: %d\n", default_tls_verify_peer, default_tls_verify_host);
-	LM_DBG("**** init curl: HTTP Proxy: %s Port %d\n", default_http_proxy, default_http_proxy_port);
+	LM_DBG("**** init curl: HTTP Proxy: %.*s Port %d\n", default_http_proxy.len, default_http_proxy.s, default_http_proxy_port);
 
 	LM_DBG("Extra: Curl supports %s %s %s \n",
 			(curl_info->features & CURL_VERSION_SSL ? "SSL" : ""),

+ 3 - 1
modules/http_client/http_client.h

@@ -43,7 +43,7 @@ extern str	default_cipher_suite_list;			/*!< List of allowed cipher suites */
 extern unsigned int	default_tls_version;		/*!< 0 = Use libcurl default */
 extern unsigned int	default_tls_verify_peer;	/*!< 0 = Do not verify TLS server cert. 1 = Verify TLS cert (default) */
 extern unsigned int	default_tls_verify_host;	/*!< 0 = Do not verify TLS server CN/SAN. 2 = Verify TLS server CN/SAN (default) */
-extern char 	*default_http_proxy;			/*!< Default HTTP proxy to use */
+extern str 	default_http_proxy;			/*!< Default HTTP proxy to use */
 extern unsigned int	default_http_proxy_port;		/*!< Default HTTP proxy port to use */
 extern unsigned int	default_http_follow_redirect;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
 extern str 	default_useragent;			/*!< Default CURL useragent. Default "Kamailio Curl " */
@@ -87,6 +87,8 @@ typedef struct _curl_con
 	curl_res_stream_t *stream;	/*!< Curl stream */
 	struct _curl_con *next;		/*!< next connection */
 	char redirecturl[512];		/*!< Last redirect URL - to use for $curlredirect(curlcon) pv */
+	char *http_proxy;			/*!< HTTP proxy for this connection */
+	unsigned int http_proxy_port;	/*!< HTTP proxy port for this connection */
 } curl_con_t;