1、首先编译OpenSSL,我是用的是gmssl;
./config --prefix=/home/fanxiangqiang/src/GmSSL-master/build
2、编译curl,这里需要指定Gmssl的安装路径;
./configure --with-http_ssl_module --with-nghttp2 --prefix=/home/fanxiangqiang/src/curl-7.76.1/build --with-ssl=/home/fanxiangqiang/src/GmSSL-master/build
编译完成就OK。
3、测试demo,单向验证链接测试网页 www.example.com;先登录上这个网站,导出DER格式证书
4、测试demo
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* <DESC>
* Simple HTTPS GET
* </DESC>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "stddef.h"
#include <time.h>
#include "curl.h"
#include "easy.h"
#include <string.h>
#include "curl.h"
#define POSTURL "https://www.example.com"
#define oneway_certification 0
// size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
// { //一次返回可能对应多次调用,此处用于拼接完整版的返回信息
// size_t realsize = size * nmemb;
// /* struct MemoryStruct *mem = (struct MemoryStruct *)data;
// mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
// if (mem->memory)
// {
// memcpy(&(mem->memory[mem->size]), ptr, realsize);
// mem->size += realsize;
// mem->memory[mem->size] = 0;
// }*/
// printf("recive data \r\n%s\r\n",ptr);
// return realsize;
// }
// size_t WriteMemoryCallback(void *buffer, size_t size, size_t nmemb, FILE *file) {
// // size_t r_size = fwrite(buffer, size, nmemb, file);
// // return r_size;
// printf("XXXXXXXXXXXXXXXXXXXXX");
// }
char path[] = "save_file.txt";
int main(void)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
FILE *file = fopen(path,"w");
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, POSTURL); //设置post address
curl_easy_setopt(curl, CURLOPT_POST,0); ///使用post
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 13L); ///设置超时
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); //重连超时
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //启用时会汇报所有的信息
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
if(!oneway_certification)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); // 验证服务器证书有效性
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);// 检验证书中的主机名和你访问的主机名一致
curl_easy_setopt(curl, CURLOPT_CAINFO, "CA.der"); // 指定 CA 证书路径
}
else
{
// 不验证服务器证书
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
}
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); //得到请求结果后的回调函数
struct curl_slist *pList = NULL;
pList = curl_slist_append(pList, "User-Agent: lanyou");
pList = curl_slist_append(pList, "Accept:application/json");
pList = curl_slist_append(pList, "Content-Type: application/json");
pList = curl_slist_append(pList, "charset:utf-8");
// pList = curl_slist_append(pList, "Expect:");
pList = curl_slist_append(pList, "Connection: close");
char temp[64] = {0};
// char *test_data = "test";
// sprintf(temp, "Content-Length: %d\r\n", strlen(test_data)); // data length
// pList = curl_slist_append(pList, temp);
// pList = curl_slist_append(pList, test_data);
// pList = curl_slist_append(pList, "\r\n");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pList);
#ifdef SKIP_PEER_VERIFICATION
/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#ifdef SKIP_HOSTNAME_VERIFICATION
/*
* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
/* Perform the request, res will get the return code */
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(pList);
long res_code = -1;
res = -1;
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code);
if (res == CURLE_OK)
{
if (res_code == 200 || res_code == 201)
{
printf("result code is %d\r\n",res_code);
}
}
curl_easy_cleanup(curl);
curl_global_cleanup();
}
printf("result code is %d\r\n",res);
return 0;
}
运行结果
* Trying 93.184.216.34:443...
* Trying 2606:2800:220:1:248:1893:25c8:1946:443...
* Immediate connect fail for 2606:2800:220:1:248:1893:25c8:1946: Network is unreachable
* Connected to www.example.com (93.184.216.34) port 443 (#0)
* ALPN, offering http/1.1
* error setting certificate verify locations, continuing anyway:
* CAfile: CA.der
* CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=California; L=Los Angeles; O=Internet Corporation for Assigned Names and Numbers; CN=www.example.org
* start date: Nov 24 00:00:00 2020 GMT
* expire date: Dec 25 23:59:59 2021 GMT
* subjectAltName: host "www.example.com" matched cert's "www.example.com"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
* SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> GET / HTTP/1.1
Host: www.example.com
User-Agent: lanyou
Accept:application/json
Content-Type: application/json
charset:utf-8
Connection: close
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Age: 580557
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Tue, 13 Jul 2021 01:16:51 GMT
< Etag: "3147526947"
< Expires: Tue, 20 Jul 2021 01:16:51 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (sab/5798)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
< Connection: close
<
* Closing connection 0
result code is 200
result code is 0
下载到的网页:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>