libcurl:Protocol "smtps" not supported or disabled in libcurl
libcurl:Protocol “smtps” not supported or disabled in libcurl
在使用libcurl来作为MUA时,开启DEBUG模式,使用smtps协议,在运行时报错:
libcurl:Protocol “smtps” not supported or disabled in libcurl
原因在于,安装libcurl时没有带着openssl。
安装包:curl-7.56.1.tar.gz
错误安装:
[jiang@localhost curl-7.56.1]$ ./configure --prefix=$HOME/libcurl
checking whether to enable maintainer-specific portions of Makefiles... no
……
configure: WARNING: SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.
configure: WARNING: Use --with-ssl, --with-gnutls, --with-polarssl, --with-cyassl, --with-nss, --with-axtls, --with-winssl, or --with-darwinssl to address this.
……
configure: Configured to build curl/libcurl:
curl version: 7.56.1
Host setup: x86_64-pc-linux-gnu
Install prefix: /home/jiang/libcurl
Compiler: gcc
SSL support: no (--with-{ssl,gnutls,nss,polarssl,mbedtls,cyassl,axtls,winssl,darwinssl} )
SSH support: no (--with-libssh2)
zlib support: no (--with-zlib)
GSS-API support: no (--with-gssapi)
TLS-SRP support: no (--enable-tls-srp)
resolver: POSIX threaded
IPv6 support: enabled
Unix sockets support: enabled
IDN support: no (--with-{libidn2,winidn})
Build libcurl: Shared=yes, Static=yes
Built-in manual: enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors: enabled (--disable-verbose)
SSPI support: no (--enable-sspi)
ca cert bundle: /etc/pki/tls/certs/ca-bundle.crt
ca cert path: no
ca fallback: no
LDAP support: no (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support: no (--enable-ldaps)
RTSP support: enabled
RTMP support: no (--with-librtmp)
metalink support: no (--with-libmetalink)
PSL support: no (libpsl not found)
HTTP2 support: disabled (--with-nghttp2)
Protocols: DICT FILE FTP GOPHER HTTP IMAP POP3 RTSP SMTP TELNET TFTP
通常在./configure生成makefile这一步,我都基本不看,能生成makefile即可,然后直接编译安装。
ATTENTION:实际应该仔细确认summary这一部分,可能存在一些潜在的运行时问题。
继续进行编译安装:
[jiang@localhost curl-7.56.1]$ make && make install
OK,到此libcurl就安装完毕。
Code:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#define FROM_ADDR "<[email protected]>"
#define TO_ADDR "<[email protected]>"
#define FROM_MAIL "[email protected]" FROM_ADDR
#define TO_MAIL "[email protected]" TO_ADDR
static const char *payload_text[] = {
"To: " TO_MAIL "\r\n",
"From: " FROM_MAIL "\r\n",
"Subject: SMTP example message\r\n",
"\r\n", /* empty line to divide headers from body, see RFC5322 */
"The body of the message starts here.\r\n",
"\r\n",
"It could be a lot of lines, could be MIME encoded, whatever.\r\n",
"Check RFC5322.\r\n",
NULL
};
struct upload_status {
int lines_read;
};
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct upload_status *upload_ctx = (struct upload_status *)userp;
const char *data;
if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
data = payload_text[upload_ctx->lines_read];
if(data) {
size_t len = strlen(data);
memcpy(ptr, data, len);
upload_ctx->lines_read++;
return len;
}
return 0;
}
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx;
upload_ctx.lines_read = 0;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "smtps://smtp.qq.com:465");
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_ADDR);
recipients = curl_slist_append(recipients, TO_ADDR);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_USERNAME, "[email protected]");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "xxxxxxxxxxxxxxxx");
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
/* DEBUG */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Send the message */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_slist_free_all(recipients);
curl_easy_cleanup(curl);
}
return (int)res;
}
编译 && 执行:
[jiang@localhost ~]$ gcc -o ssl ssl.c -I/home/jiang/libcurl/include -L /home/jiang/libcurl/lib -lcurl
[jiang@localhost ~]$ ./ssl
* Protocol smtps not supported or disabled in libcurl
* Unsupported protocol
curl_easy_perform() failed: Unsupported protocol
仔细回头看看,想想。
libcurl如果使用smtps,即使用TLS/SSL,那必然涉及到加解密算法,谁来做这个工作呢?
刚刚似乎安装libcurl时没有带着openssl?
实际可能由于openssl版本和libcurl要求的openssl版本不一致或其他原因,导致./configure在生成libcurl的makefile时,并没有(发现)已存在的openssl库。
解决办法:
重新安装/升级openssl:
[root@localhost ~]# yum install openssl-devel -y
重新安装libcurl:
[jiang@localhost curl-7.56.1]$ ./configure --prefix=$HOME/libcurl
……
configure: Configured to build curl/libcurl:
curl version: 7.56.1
Host setup: x86_64-pc-linux-gnu
Install prefix: /home/jiang/libcurl
Compiler: gcc
SSL support: enabled (OpenSSL)
SSH support: no (--with-libssh2)
zlib support: enabled
GSS-API support: no (--with-gssapi)
TLS-SRP support: no (--enable-tls-srp)
resolver: POSIX threaded
IPv6 support: enabled
Unix sockets support: enabled
IDN support: no (--with-{libidn2,winidn})
Build libcurl: Shared=yes, Static=yes
Built-in manual: enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors: enabled (--disable-verbose)
SSPI support: no (--enable-sspi)
ca cert bundle: /etc/pki/tls/certs/ca-bundle.crt
ca cert path: no
ca fallback: no
LDAP support: no (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support: no (--enable-ldaps)
RTSP support: enabled
RTMP support: no (--with-librtmp)
metalink support: no (--with-libmetalink)
PSL support: no (libpsl not found)
HTTP2 support: disabled (--with-nghttp2)
Protocols: DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP
[jiang@localhost curl-7.56.1]$ make && make install
仔细对比两次./configure生成输出的summary:
Protocols: DICT FILE FTP GOPHER HTTP IMAP POP3 RTSP SMTP TELNET TFTP
Protocols: DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS POP3 POP3S RTSP SMB SMBS SMTP
即,通过安装/升级openssl,使得在安装libcurl生成makefile时,让其发现openssl的存在,带着openssl编译安装,以支持所有需要TLS/SSL的协议(HTTPS、SMTPS等)。
代码编译&&执行如下:
[jiang@localhost ~]$ gcc -o ssl ssl.c -I/home/jiang/libcurl/include -L /home/jiang/libcurl/lib -lcurl
[jiang@localhost ~]$ ./ssl
* Rebuilt URL to: smtps://smtp.qq.com:465/
* Trying 14.17.57.241...
* TCP_NODELAY set
* Connected to smtp.qq.com (14.17.57.241) port 465 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLSv1.2 / AES128-SHA256
* Server certificate:
* subject: C=CN; ST=Guangdong; L=Shenzhen; O=Shenzhen Tencent Computer Systems Company Limited; OU=R&D; CN=pop.qq.com
* start date: Sep 7 00:00:00 2016 GMT
* expire date: Dec 7 23:59:59 2018 GMT
* issuer: C=US; O=GeoTrust Inc.; CN=GeoTrust SSL CA - G3
* SSL certificate verify ok.
< 220 smtp.qq.com Esmtp QQ Mail Server
> EHLO localhost
< 250-smtp.qq.com
< 250-PIPELINING
< 250-SIZE 73400320
< 250-AUTH LOGIN PLAIN
< 250-AUTH=LOGIN
< 250-MAILCOMPRESS
< 250 8BITMIME
> AUTH LOGIN
< 334 VXNlcm5hbWU6
> MTE1ODgwMTQxMUBxcS5jb20=
< 334 UGFzc3dvcmQ6
> YmJ1eXVwZnphdmFoaGhpYw==
< 235 Authentication successful
> MAIL FROM:<[email protected]>
< 250 Ok
> RCPT TO:<[email protected]>
< 250 Ok
> DATA
< 354 End data with <CR><LF>.<CR><LF>
< 250 Ok: queued as
* Connection #0 to host smtp.qq.com left intact
OK,发送成功(TLS/SSL)。
还有一种可能,也会导致上面的错误信息:
可执行文件链接的动态库不是新版的,支持SMTPS的动态库,而是旧版本的libcurl动态库。
[jiang@localhost ~]$ ldd ./ssl
linux-vdso.so.1 => (0x00007ffc6cbeb000)
libcurl.so.4 => /usr/lib64/libcurl.so.4 (0x000000312ec00000)
……
[jiang@localhost ~]$ ./ssl
* Protocol smtps not supported or disabled in libcurl
* Unsupported protocol
curl_easy_perform() failed: Unsupported protocol
通过设置LD_LIBRARY_PATH,使其找到正确的libcurl动态库(当然,也存在很多其他方法啦):
[[email protected] ~]$ export LD_LIBRARY_PATH=$HOME/libcurl/lib:$LD_LIBRARY_PATH
[[email protected] ~]$ ./ssl
* Rebuilt URL to: smtps://smtp.qq.com:465/
* Trying 14.17.57.241...
* TCP_NODELAY set
* Connected to smtp.qq.com (14.17.57.241) port 465 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
……
总结:
有两种原因导致:
Protocol “smtps” not supported or disabled in libcurl
1.在./configure生成libcurl的makefile时,可能由于openssl库安装不正确、版本等问题导致configure找不到openssl库
2.执行可执行文件时,动态链接器ld找到的不是正确的,支持TLS/SSL的libcurl,而是其他版本、不支持TLS/SSL的libcurl
同理,可能存在:
Protocol “https” not supported or disabled in libcurl
当运行时发现这个问题,可以先检查下libcurl是否支持openssl?安装libcurl时是否是带着openssl进行编译的?
上一篇: 数据库体系结构
下一篇: vue2.0常见组件安装