Parcourir la source

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

Hugh Waite il y a 9 ans
Parent
commit
64764ff9ce
5 fichiers modifiés avec 84 ajouts et 35 suppressions
  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_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_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 */
 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 */
 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_proxy_port = 0;		/*!< Default HTTP proxy port to use */
 unsigned int	default_http_follow_redirect = 0;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
 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 },
 	{"tlsclientcert", PARAM_STRING, &default_tls_clientcert },
 	{"tlsclientkey", PARAM_STRING, &default_tls_clientkey },
 	{"tlsclientkey", PARAM_STRING, &default_tls_clientkey },
 	{"tlscipherlist", PARAM_STRING, &default_cipher_suite_list },
 	{"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 },
 	{"httpproxyport", PARAM_INT, &default_http_proxy_port },
 	{"httpproxy", PARAM_STRING, &default_http_proxy},
 	{"httpproxy", PARAM_STRING, &default_http_proxy},
 	{"httpredirect", PARAM_INT, &default_http_follow_redirect },
 	{"httpredirect", PARAM_INT, &default_http_follow_redirect },
@@ -150,13 +152,6 @@ static param_export_t params[] = {
     	{0, 0, 0}
     	{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
  * \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_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_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 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 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_proxy_port;		/*!< Default HTTP proxy port to use */
 extern unsigned int	default_http_follow_redirect;	/*!< Follow HTTP redirects CURLOPT_FOLLOWLOCATION */
 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 cacert;			/*!< File name of CA cert to use */
 	str clientcert;			/*!< File name of CA client cert */
 	str clientcert;			/*!< File name of CA client cert */
 	str clientkey;			/*!< File name of CA client key */
 	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 */
 	int http_follow_redirect;	/*!< TRUE if we should follow HTTP 302 redirects */
 	unsigned int port;		/*!< The port to connect to */
 	unsigned int port;		/*!< The port to connect to */
 	int timeout;			/*!< Timeout for this connection */
 	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
  *		useragent
  *		failover
  *		failover
  *		maxdatasize
  *		maxdatasize
- *		verifyserver
+ *		verifypeer
+ *		verifyhost
  *
  *
  */
  */
 int curl_parse_param(char *val)
 int curl_parse_param(char *val)
@@ -116,7 +117,8 @@ int curl_parse_param(char *val)
 	unsigned int timeout	= default_connection_timeout;
 	unsigned int timeout	= default_connection_timeout;
 	str useragent   = { default_useragent, strlen(default_useragent) };
 	str useragent   = { default_useragent, strlen(default_useragent) };
 	unsigned int http_follow_redirect = default_http_follow_redirect;
 	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;
 	str in;
 	char *p;
 	char *p;
@@ -305,17 +307,28 @@ int curl_parse_param(char *val)
 					maxdatasize = default_maxdatasize;
 					maxdatasize = default_maxdatasize;
 				}
 				}
 				LM_DBG("curl [%.*s] - timeout [%d]\n", pit->name.len, pit->name.s, 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 */
 					/* 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 {
 			} else {
 				LM_ERR("curl Unknown parameter [%.*s] \n", pit->name.len, pit->name.s);
 				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,
 			name.len, name.s, url.len, url.s, username.len, username.s,
 			password.len, password.s, failover.len, failover.s, timeout,
 			password.len, password.s, failover.len, failover.s, timeout,
 			useragent.len, useragent.s, maxdatasize);
 			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) {
 	if(conparams != NULL) {
 		free_params(conparams);
 		free_params(conparams);
@@ -347,7 +361,8 @@ int curl_parse_param(char *val)
 	cc->url = url;
 	cc->url = url;
 	cc->clientcert = client_cert;
 	cc->clientcert = client_cert;
 	cc->clientkey = client_key;
 	cc->clientkey = client_key;
-	cc->verify_server = verifyserver;
+	cc->verify_peer = verify_peer;
+	cc->verify_host = verify_host;
 	cc->timeout = timeout;
 	cc->timeout = timeout;
 	cc->maxdatasize = maxdatasize;
 	cc->maxdatasize = maxdatasize;
 	cc->http_follow_redirect = http_follow_redirect;
 	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>
 				</programlisting>
 			</example>
 			</example>
 		</section>
 		</section>
-		<section id="curl.p.tlsverifyserver">
-			<title><varname>tlsverifyserver</varname> (int)</title>
+		<section id="curl.p.tlsverifypeer">
+			<title><varname>tlsverifypeer</varname> (int)</title>
 			<para>
 			<para>
 			If set to 0, TLS verification of the server certificate
 			If set to 0, TLS verification of the server certificate
 			is disabled. This means that the connection will get 
 			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.
 			that is meant to receive data.
 			</para>
 			</para>
 			<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.
 			is configured, the server TLS certificate will be validated.
 			If validation fails, the connection fails.
 			If validation fails, the connection fails.
 			</para>
 			</para>
 			<para>
 			<para>
+			See the curl documenation for more details.
+			http://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
 			</para>
 			</para>
 			<example>
 			<example>
-			<title>Set <varname>tlsverifyserver</varname> parameter</title>
+			<title>Set <varname>tlsverifypeer</varname> parameter</title>
 				<programlisting format="linespecific">
 				<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>
 				</programlisting>
 			</example>
 			</example>
@@ -309,8 +337,13 @@ modparam("curl", "tlsverifyserver", 1)
 				useragent modparam.
 				useragent modparam.
 				</para></listitem>
 				</para></listitem>
 				<listitem><para>
 				<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>
 				</para></listitem>
 			</itemizedlist>
 			</itemizedlist>
 			</para>
 			</para>

+ 8 - 4
modules/curl/functions.c

@@ -55,7 +55,8 @@ typedef struct {
     char *clientkey;
     char *clientkey;
     char *cacert;
     char *cacert;
     char *ciphersuites;
     char *ciphersuites;
-    unsigned int verify_server;
+    unsigned int verify_peer;
+    unsigned int verify_host;
     unsigned int timeout;
     unsigned int timeout;
     unsigned int http_follow_redirect;
     unsigned int http_follow_redirect;
     unsigned int oneline;
     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_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_NOSIGNAL, (long) 1);
     res |= curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) params->timeout);
     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.clientkey = conn->clientkey.s;
 	query_params.cacert = default_tls_cacert;
 	query_params.cacert = default_tls_cacert;
 	query_params.ciphersuites = default_cipher_suite_list;
 	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.timeout = conn->timeout;
 	query_params.http_follow_redirect = conn->http_follow_redirect;
 	query_params.http_follow_redirect = conn->http_follow_redirect;
 	query_params.oneline = 0;
 	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.clientkey = NULL;
 	query_params.cacert = NULL;
 	query_params.cacert = NULL;
 	query_params.ciphersuites = 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.timeout = default_connection_timeout;
 	query_params.http_follow_redirect = default_http_follow_redirect;
 	query_params.http_follow_redirect = default_http_follow_redirect;
 	query_params.oneline = 1;
 	query_params.oneline = 1;