C语言实现Openssl+CURL+nginx 单向认证

这段时间在做本地终端链接服务器的工作,在此记录下,以免将来忘了。
首先有一个已经搭建好的nginx服务器,并且能够实现单向认证。
然后现在服务器端生成证书请求文件。
1.用openssl创建私钥

openssl genrsa -out server.key

2.用私钥创建证书请求文件

openssl req -new -key server.key -out server.csr

CA签发证书:

CA是专门签发证书的权威机构,处于证书的最顶端。自签是用自己的私钥给证书签名,CA签发则是用CA的私钥给自己的证书签名来保证证书的可靠性。因为是要实现单向认证,所以就要有CA进行认证。因为CA认证机构是要花钱的,因此自己创建CA。
1.生成CA私钥和证书

openssl req -new -x509 -keyout ca.key -out ca.crt

2.生成CA签名证书

openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config openssl.cnf

这里我用openssl.cnf来自定义生成ca.crt的路径。openssl.cnf默认的存放路径在/etc/pki/tls
在openssl.cnf中只修改了一行

#dir        = /etc/pki/CA  //默认地址
dir             = /home/pki/ServerCert 
certs           = $dir/certs  

创建完成后,本地需要的文件是ca.crt,nginx服务中需要的是server.crt。
在nginx中配置证书如下:

server {
    listen       443 ssl;
    server_name  localhost;
    ssl on;
    ssl_certificate /etc/nginx/pki/server.crt;
    ssl_certificate_key /etc/nginx/pki/server.key;
    ssl_protocols TLSv1.2;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;
   ...
   ...
   }

下一步,在本地尝试用curl工具进行链接测试。

curl -v --cacert ca.crt https://198.168.1.145

得到服务器的登录页面的html。
注意,不要在curl后加 -k,-k是忽略了证书的正确与否,不能保证是否实现了认证。
最后用c代码实现这个链接过程。

#include 
#include 
#include 
#include "lic.h"
#include 

#define FILENAME    "sr.dat"
#define URL         "https://192.168.1.145"

size_t write_data(void* buffer,size_t size,size_t nmemb,void *stream)
{
    FILE *fptr = (FILE*)stream;
    fwrite(buffer,size,nmemb,fptr);
    return size*nmemb;
}

int download_license(char *UniqueID, char *OderNum)
{
    CURL *curl;
    CURLcode res;
    FILE * fptr;
    char post_parameter[4096];                              //传入的参数
    struct curl_slist *http_header = NULL;                  //定义参数头
    struct curl_slist *headers = NULL;
    char *pCaPath = "/home/pki/ca.crt";
    //char *UniqueID = arg[1];
    //char *OderNum = arg[2];

    if (! UniqueID)
    {
        fprintf(stderr,"Please enter unquieID!\n");         //没有输入UnquieID
        exit(0);
    }
    else
    {

        if (! OderNum)
        {
            fprintf(stderr,"Please enter oder num!\n");     //没有输入Oder num
            exit(0);
        }
        else
        {
            strcpy(post_parameter,"licenseID=%22");         //拼接输入的参数
            strcat(post_parameter, UniqueID);
            strcat(post_parameter, "%22&OderNumber=%22");
            strcat(post_parameter, OderNum);
            strcat(post_parameter, "%22");
        }
    }
    if ((fptr = fopen(FILENAME,"w")) == NULL)
    {
        fprintf(stderr,"fopen file error:%s\n",FILENAME);   //文件打开错误
        return -1;
    }
    headers = curl_slist_append(headers, "Host: 192.168.65.128");
    headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0");
    headers = curl_slist_append(headers, "Accept: application/json, text/javascript, */*; q=0.01");
    headers = curl_slist_append(headers, "Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
    headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");
    headers = curl_slist_append(headers, "X-Requested-With: XMLHttpRequest");
    headers = curl_slist_append(headers, "Cookie: lastTimeLines=0; cipher_session=1; cipher_key=1; down=1");

    curl = curl_easy_init();
    if (!curl)
    {
        fprintf(stderr,"curl init failed\n");
        return -1;
    }
    //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);  
    //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);//openssl编译时使用curl官网或者firefox导出的第三方根证书文件 
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
    curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头
    curl_easy_setopt(curl, CURLOPT_URL, URL); //url地址
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS,post_parameter); //post参数
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,write_data); //对返回的数据进行操作的函数地址

    curl_easy_setopt(curl, CURLOPT_WRITEDATA,fptr); //这是write_data的第四个参数值

    res = curl_easy_perform(curl);

    if (res != CURLE_OK)
    {
        switch(res)
        {
        case CURLE_UNSUPPORTED_PROTOCOL:
            fprintf(stderr,"不支持的协议,由URL的头部指定\n");
        case CURLE_COULDNT_CONNECT:
            fprintf(stderr,"不能连接到remote主机或者代理\n");
        case CURLE_HTTP_RETURNED_ERROR:
            fprintf(stderr,"http返回错误\n");
        case CURLE_READ_ERROR:
            fprintf(stderr,"读本地文件错误\n");
        default:
            fprintf(stderr,"返回值:%d\n",res);
        }
        return -1;
    }

    close(fptr);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
}

你可能感兴趣的:(c语言,curl,openssl,nginx,单向认证)