Browse Source

curl: Add curl verifyhost option
- Renamed verifyserver to verifypeer to match libcurl
- Added default verifyhost modparam
- Added per-connection verifyhost override

Hugh Waite 9 years ago
parent
commit
64764ff9ce
5 changed files with 84 additions and 35 deletions
  1. 4 9
      modules/curl/curl.c
  2. 4 2
      modules/curl/curl.h
  3. 28 13
      modules/curl/curlcon.c
  4. 40 7
      modules/curl/doc/curl_admin.xml
  5. 8 4
      modules/curl/functions.c

+ 4 - 9
modules/curl/curl.c

@@ -77,7 +77,8 @@ char		*default_tls_cacert = NULL;		/*!< File name: Default CA cert to use for cu
 char		*default_tls_clientcert = NULL;		/*!< File name: Default client certificate to use for curl TLS connection */
 char		*default_tls_clientkey = NULL;		/*!< File name: Key in PEM format that belongs to client cert */
 char		*default_cipher_suite_list = NULL;		/*!< List of allowed cipher suites */
-unsigned int	default_tls_verifyserver = 1;		/*!< 0 = Do not verify TLS server cert. 1 = Verify TLS cert (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 */
 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 */
@@ -141,7 +142,8 @@ static param_export_t params[] = {
 	{"tlsclientcert", PARAM_STRING, &default_tls_clientcert },
 	{"tlsclientkey", PARAM_STRING, &default_tls_clientkey },
 	{"tlscipherlist", PARAM_STRING, &default_cipher_suite_list },
-	{"tlsverifyserver", PARAM_INT, &default_tls_verifyserver },
+	{"tlsverifypeer", PARAM_INT, &default_tls_verify_peer },
+	{"tlsverifyhost", PARAM_INT, &default_tls_verify_host },
 	{"httpproxyport", PARAM_INT, &default_http_proxy_port },
 	{"httpproxy", PARAM_STRING, &default_http_proxy},
 	{"httpredirect", PARAM_INT, &default_http_follow_redirect },
@@ -150,13 +152,6 @@ static param_export_t params[] = {
     	{0, 0, 0}
 };
 
-//		str	default_tls_clientcert;			/*!< File name: Default client certificate to use for curl TLS connection */
-//		str	default_tls_clientkey;			/*!< File name: Key in PEM format that belongs to client cert */
-//		int	default_tls_verifyserver = 1;		/*!< 0 = Do not verify TLS server cert. 1 = Verify TLS cert (default) */
-//		str	default_http_proxy;			/*!< Default HTTP proxy to use */
-//		int	default_http_proxy_port;		/*!< Default HTTP proxy port to use */
-//		int	default_http_follow_redirect = 0;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
-//		str	default_useragent;			/*!< Default CURL useragent. Default "Kamailio Curl " */
 
 /*!
  * \brief Exported Pseudo variables

+ 4 - 2
modules/curl/curl.h

@@ -40,7 +40,8 @@ extern char	*default_tls_cacert;			/*!< File name: Default CA cert to use for cu
 extern char	*default_tls_clientcert;		/*!< File name: Default client certificate to use for curl TLS connection */
 extern char	*default_tls_clientkey;			/*!< File name: Key in PEM format that belongs to client cert */
 extern char	*default_cipher_suite_list;			/*!< List of allowed cipher suites */
-extern unsigned int	default_tls_verifyserver;		/*!< 0 = Do not verify TLS server cert. 1 = Verify TLS cert (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 unsigned int	default_http_proxy_port;		/*!< Default HTTP proxy port to use */
 extern unsigned int	default_http_follow_redirect;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
@@ -74,7 +75,8 @@ typedef struct _curl_con
 	str cacert;			/*!< File name of CA cert to use */
 	str clientcert;			/*!< File name of CA client cert */
 	str clientkey;			/*!< File name of CA client key */
-	int verify_server;		/*!< TRUE if server cert to be verified */
+	int verify_peer;		/*!< TRUE if server cert to be verified */
+	int verify_host;		/*!< TRUE if server CN/SAN to be verified */
 	int http_follow_redirect;	/*!< TRUE if we should follow HTTP 302 redirects */
 	unsigned int port;		/*!< The port to connect to */
 	int timeout;			/*!< Timeout for this connection */

+ 28 - 13
modules/curl/curlcon.c

@@ -96,7 +96,8 @@ curl_con_t* curl_get_connection(str *name)
  *		useragent
  *		failover
  *		maxdatasize
- *		verifyserver
+ *		verifypeer
+ *		verifyhost
  *
  */
 int curl_parse_param(char *val)
@@ -116,7 +117,8 @@ int curl_parse_param(char *val)
 	unsigned int timeout	= default_connection_timeout;
 	str useragent   = { default_useragent, strlen(default_useragent) };
 	unsigned int http_follow_redirect = default_http_follow_redirect;
-	unsigned int verifyserver = default_tls_verifyserver;
+	unsigned int verify_peer = default_tls_verify_peer;
+	unsigned int verify_host = default_tls_verify_host;
 
 	str in;
 	char *p;
@@ -305,17 +307,28 @@ int curl_parse_param(char *val)
 					maxdatasize = default_maxdatasize;
 				}
 				LM_DBG("curl [%.*s] - timeout [%d]\n", pit->name.len, pit->name.s, maxdatasize);
-			} else if(pit->name.len==12 && strncmp(pit->name.s, "verifyserver", 7)==0) {
-				if(str2int(&tok, &verifyserver)!=0) {
+			} else if(pit->name.len==12 && strncmp(pit->name.s, "verifypeer", 7)==0) {
+				if(str2int(&tok, &verify_peer)!=0) {
 					/* Bad integer */
-					LM_DBG("curl connection [%.*s]: verifyserver bad value. Using default\n", name.len, name.s);
-					verifyserver = default_tls_verifyserver;
+					LM_DBG("curl connection [%.*s]: verifypeer bad value. Using default\n", name.len, name.s);
+					verify_peer = default_tls_verify_peer;
 				}
-				if (verifyserver != 0 && verifyserver != 1) {
-					LM_DBG("curl connection [%.*s]: verifyserver bad value. Using default\n", name.len, name.s);
-					verifyserver = default_tls_verifyserver;
+				if (verify_peer != 0 && verify_peer != 1) {
+					LM_DBG("curl connection [%.*s]: verifypeer bad value. Using default\n", name.len, name.s);
+					verify_peer = default_tls_verify_peer;
 				}
-				LM_DBG("curl [%.*s] - verifyserver [%d]\n", pit->name.len, pit->name.s, verifyserver);
+				LM_DBG("curl [%.*s] - verifypeer [%d]\n", pit->name.len, pit->name.s, verify_peer);
+			} else if(pit->name.len==12 && strncmp(pit->name.s, "verifyhost", 7)==0) {
+				if(str2int(&tok, &verify_host)!=0) {
+					/* Bad integer */
+					LM_DBG("curl connection [%.*s]: verifyhost bad value. Using default\n", name.len, name.s);
+					verify_host = default_tls_verify_host;
+				}
+				if (verify_host != 0 && verify_host != 1) {
+					LM_DBG("curl connection [%.*s]: verifyhost bad value. Using default\n", name.len, name.s);
+					verify_host = default_tls_verify_host;
+				}
+				LM_DBG("curl [%.*s] - verifyhost [%d]\n", pit->name.len, pit->name.s, verify_host);
 			} else {
 				LM_ERR("curl Unknown parameter [%.*s] \n", pit->name.len, pit->name.s);
 			}
@@ -328,8 +341,9 @@ int curl_parse_param(char *val)
 			name.len, name.s, url.len, url.s, username.len, username.s,
 			password.len, password.s, failover.len, failover.s, timeout,
 			useragent.len, useragent.s, maxdatasize);
-	LM_DBG("cname: [%.*s] client_cert [%.*s] client_key [%.*s] verifyserver [%d]\n",
-			name.len, name.s, client_cert.len, client_cert.s, client_key.len, client_key.s, verifyserver);
+	LM_DBG("cname: [%.*s] client_cert [%.*s] client_key [%.*s] verify_peer [%d] verify_host [%d]\n",
+			name.len, name.s, client_cert.len, client_cert.s, client_key.len, client_key.s,
+			verify_peer, verify_host);
 
 	if(conparams != NULL) {
 		free_params(conparams);
@@ -347,7 +361,8 @@ int curl_parse_param(char *val)
 	cc->url = url;
 	cc->clientcert = client_cert;
 	cc->clientkey = client_key;
-	cc->verify_server = verifyserver;
+	cc->verify_peer = verify_peer;
+	cc->verify_host = verify_host;
 	cc->timeout = timeout;
 	cc->maxdatasize = maxdatasize;
 	cc->http_follow_redirect = http_follow_redirect;

+ 40 - 7
modules/curl/doc/curl_admin.xml

@@ -245,8 +245,8 @@ modparam("curl", "tlscipherlist", "ecdhe_ecdsa_aes_128_gcm_sha_256,rsa_aes_128_g
 				</programlisting>
 			</example>
 		</section>
-		<section id="curl.p.tlsverifyserver">
-			<title><varname>tlsverifyserver</varname> (int)</title>
+		<section id="curl.p.tlsverifypeer">
+			<title><varname>tlsverifypeer</varname> (int)</title>
 			<para>
 			If set to 0, TLS verification of the server certificate
 			is disabled. This means that the connection will get 
@@ -255,17 +255,45 @@ modparam("curl", "tlscipherlist", "ecdhe_ecdsa_aes_128_gcm_sha_256,rsa_aes_128_g
 			that is meant to receive data.
 			</para>
 			<para>
-			IF set to 1, default setting, and one or more CA certificates
+			If set to 1, default setting, and one or more CA certificates
 			is configured, the server TLS certificate will be validated.
 			If validation fails, the connection fails.
 			</para>
 			<para>
+			See the curl documenation for more details.
+			http://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
 			</para>
 			<example>
-			<title>Set <varname>tlsverifyserver</varname> parameter</title>
+			<title>Set <varname>tlsverifypeer</varname> parameter</title>
 				<programlisting format="linespecific">
 ...
-modparam("curl", "tlsverifyserver", 1)
+modparam("curl", "tlsverifypeer", 1)
+...
+				</programlisting>
+			</example>
+		</section>
+		<section id="curl.p.tlsverifyhost">
+			<title><varname>tlsverifyhost</varname> (int)</title>
+			<para>
+			If set to 0, domain verification of the server certificate
+			is disabled. This means that the connection will get 
+			encrypted but there is no check that data will be sent to the
+			host that is meant to receive it. Disable with caution.
+			</para>
+			<para>
+			If set to 2, default setting, the hostname in the URL will
+			be verified against the Common Name or Subject Alt Name
+			in the certificate. If validation fails, the connection fails.
+			</para>
+			<para>
+			See the curl documentation for more details.
+			http://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
+			</para>
+			<example>
+			<title>Set <varname>tlsverifyhost</varname> parameter</title>
+				<programlisting format="linespecific">
+...
+modparam("curl", "tlsverifyhost", 2)
 ...
 				</programlisting>
 			</example>
@@ -309,8 +337,13 @@ modparam("curl", "tlsverifyserver", 1)
 				useragent modparam.
 				</para></listitem>
 				<listitem><para>
-				<emphasis>verifyserver</emphasis> Enables or disables server certificate verification.
-				Overrides tlsverifyserver modparam.
+				<emphasis>verifypeer</emphasis> Set to 1 to enable or 0 to disable server
+				certificate verification.
+				Overrides tlsverifypeer modparam.
+				</para></listitem>
+				<emphasis>verifyhost</emphasis> Set to 2 to enable or 0 to disable server
+				hostname verification.
+				Overrides tlsverifyhost modparam.
 				</para></listitem>
 			</itemizedlist>
 			</para>

+ 8 - 4
modules/curl/functions.c

@@ -55,7 +55,8 @@ typedef struct {
     char *clientkey;
     char *cacert;
     char *ciphersuites;
-    unsigned int verify_server;
+    unsigned int verify_peer;
+    unsigned int verify_host;
     unsigned int timeout;
     unsigned int http_follow_redirect;
     unsigned int oneline;
@@ -177,7 +178,8 @@ 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);
     }
 
-    res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) params->verify_server);
+    res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) params->verify_peer);
+    res |= curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long) params->verify_host);
 
     res |= curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long) 1);
     res |= curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) params->timeout);
@@ -365,7 +367,8 @@ int curl_con_query_url(struct sip_msg* _m, const str *connection, const str* url
 	query_params.clientkey = conn->clientkey.s;
 	query_params.cacert = default_tls_cacert;
 	query_params.ciphersuites = default_cipher_suite_list;
-	query_params.verify_server = conn->verify_server;
+	query_params.verify_peer = conn->verify_peer;
+	query_params.verify_host = conn->verify_host;
 	query_params.timeout = conn->timeout;
 	query_params.http_follow_redirect = conn->http_follow_redirect;
 	query_params.oneline = 0;
@@ -410,7 +413,8 @@ int http_query(struct sip_msg* _m, char* _url, str* _dst, char* _post)
 	query_params.clientkey = NULL;
 	query_params.cacert = NULL;
 	query_params.ciphersuites = NULL;
-	query_params.verify_server = default_tls_verifyserver;
+	query_params.verify_peer = default_tls_verify_peer;
+	query_params.verify_host = default_tls_verify_host;
 	query_params.timeout = default_connection_timeout;
 	query_params.http_follow_redirect = default_http_follow_redirect;
 	query_params.oneline = 1;