barbieri pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=4aca800bde64f649a111a160ab4129a444762e7c
commit 4aca800bde64f649a111a160ab4129a444762e7c Author: Gustavo Sverzut Barbieri <[email protected]> Date: Tue Nov 29 02:16:47 2016 -0200 efl_net_dialer_http: export SSL controls. verify peer, hostname and set CA/CRL files. --- src/lib/ecore_con/ecore_con_url_curl.h | 3 ++ src/lib/ecore_con/efl_net_dialer_http.c | 81 ++++++++++++++++++++++++++++++++ src/lib/ecore_con/efl_net_dialer_http.eo | 28 +++++++++++ 3 files changed, 112 insertions(+) diff --git a/src/lib/ecore_con/ecore_con_url_curl.h b/src/lib/ecore_con/ecore_con_url_curl.h index 094c286..42eae54 100644 --- a/src/lib/ecore_con/ecore_con_url_curl.h +++ b/src/lib/ecore_con/ecore_con_url_curl.h @@ -251,12 +251,14 @@ typedef enum CINIT(CONNECTTIMEOUT_MS, LONG, 156), CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), CINIT(HTTPGET, LONG, 80), + CINIT(SSL_VERIFYHOST, LONG, 81), CINIT(COOKIEJAR, OBJECTPOINT, 82), CINIT(HTTP_VERSION, LONG, 84), CINIT(FTP_USE_EPSV, LONG, 85), CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), CINIT(DEBUGDATA, OBJECTPOINT, 95), CINIT(COOKIESESSION, LONG, 96), + CINIT(CAPATH, STRINGPOINT, 97), CINIT(BUFFERSIZE, LONG, 98), CINIT(NOSIGNAL, LONG, 99), CINIT(PROXYTYPE, LONG, 101), @@ -268,6 +270,7 @@ typedef enum CINIT(COOKIELIST, OBJECTPOINT, 135), CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + CINIT(CRLFILE, STRINGPOINT, 169), CINIT(USERNAME, OBJECTPOINT, 173), CINIT(PASSWORD, OBJECTPOINT, 174), CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index cf6c4a9..531b499 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -201,6 +201,12 @@ typedef struct Efl_Net_Http_Authentication_Method method; Eina_Bool restricted; } authentication; + struct { + Eina_Stringshare *ca; + Eina_Stringshare *crl; + Eina_Bool verify_peer; + Eina_Bool verify_hostname; + } ssl; Efl_Future *pending_close; unsigned int in_curl_callback; SOCKET fd; @@ -1084,6 +1090,7 @@ _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) efl_net_dialer_http_method_set(o, "GET"); efl_net_dialer_http_version_set(o, EFL_NET_HTTP_VERSION_V1_1); efl_net_dialer_http_allow_redirects_set(o, EINA_TRUE); + efl_net_dialer_http_ssl_verify_set(o, EINA_TRUE, EINA_TRUE); efl_net_dialer_timeout_dial_set(o, 30.0); return o; } @@ -1163,6 +1170,8 @@ _efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) eina_stringshare_replace(&pd->response.content_type, NULL); eina_stringshare_replace(&pd->authentication.username, NULL); _secure_free(&pd->authentication.password); + eina_stringshare_replace(&pd->ssl.ca, NULL); + eina_stringshare_replace(&pd->ssl.crl, NULL); } static void @@ -2265,6 +2274,78 @@ _efl_net_dialer_http_cookie_jar_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data return pd->cookie_jar; } +EOLIAN static void +_efl_net_dialer_http_ssl_verify_set(Eo *o, Efl_Net_Dialer_Http_Data *pd, Eina_Bool peer, Eina_Bool hostname) +{ + CURLcode r; + + r = curl_easy_setopt(pd->easy, CURLOPT_SSL_VERIFYPEER, (long)peer); + if (r != CURLE_OK) + ERR("dialer=%p could not set SSL verify peer %d: %s", + o, peer, curl_easy_strerror(r)); + + /* VERIFYHOST used to take 1 as debug, + * it requires 2 to really enable it. + */ + r = curl_easy_setopt(pd->easy, CURLOPT_SSL_VERIFYHOST, (long)hostname * 2); + if (r != CURLE_OK) + ERR("dialer=%p could not set SSL verify hostname %d: %s", + o, hostname, curl_easy_strerror(r)); + + pd->ssl.verify_peer = peer; + pd->ssl.verify_hostname = hostname; +} + +EOLIAN static void +_efl_net_dialer_http_ssl_verify_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, Eina_Bool *peer, Eina_Bool *hostname) +{ + if (peer) *peer = pd->ssl.verify_peer; + if (hostname) *hostname = pd->ssl.verify_hostname; +} + +EOLIAN static void +_efl_net_dialer_http_ssl_certificate_authority_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, const char *path) +{ + CURLcode r; + struct stat st; + + if (path && (stat(path, &st) == 0) && (S_ISDIR(st.st_mode))) + r = curl_easy_setopt(pd->easy, CURLOPT_CAPATH, path); + else + r = curl_easy_setopt(pd->easy, CURLOPT_CAINFO, path); + + if (r != CURLE_OK) + ERR("dialer=%p could not set SSL CA '%s': %s", + o, path, curl_easy_strerror(r)); + + eina_stringshare_replace(&pd->ssl.ca, path); +} + +EOLIAN static const char * +_efl_net_dialer_http_ssl_certificate_authority_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd) +{ + return pd->ssl.ca; +} + +EOLIAN static void +_efl_net_dialer_http_ssl_certificate_revogation_list_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, const char *path) +{ + CURLcode r; + + r = curl_easy_setopt(pd->easy, CURLOPT_CRLFILE, path); + if (r != CURLE_OK) + ERR("dialer=%p could not set SSL CRL '%s': %s", + o, path, curl_easy_strerror(r)); + + eina_stringshare_replace(&pd->ssl.crl, path); +} + +EOLIAN static const char * +_efl_net_dialer_http_ssl_certificate_revogation_list_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd) +{ + return pd->ssl.crl; +} + EOLIAN static long _efl_net_dialer_http_date_parse(Efl_Class *cls EINA_UNUSED, void *cd EINA_UNUSED, const char *str) { diff --git a/src/lib/ecore_con/efl_net_dialer_http.eo b/src/lib/ecore_con/efl_net_dialer_http.eo index 5c41d78..894a765 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.eo +++ b/src/lib/ecore_con/efl_net_dialer_http.eo @@ -335,6 +335,34 @@ class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Sizer) { } } + @property ssl_verify { + [[If remote peer's SSL certificate should be verified. + + Defaults to both peer and hostname verification (all $true). + ]] + values { + peer: bool; [[If $true, SSL certificate will be verified. If $false, untrusted certificates (including self signed) will be accepted.]] + hostname: bool; [[If $true, in addition to SSL certificate validation, the server name will be matched to certificate DNS entries]] + } + } + + @property ssl_certificate_authority { + [[Overrides the CA (Certificate Authority) path or directory. + + Defaults to system setup. + ]] + values { + path: string; [[Directory or file path to use for Certificate Authority]] + } + } + + @property ssl_certificate_revogation_list { + [[Defines a CRL (Certificate Revogation List) path to use.]] + values { + file: string; [[File path to use for CRL]] + } + } + date_parse @class { [[Parse the given string as time in seconds since 1/1/1970. --
