您的位置:首页 > 运维架构

Openssl建立SSL双向认证连接源码

2011-11-11 18:36 591 查看
 (作者:陈波,2011-11-16,转载请注明 Form:http://blog.csdn.net/jinhill/article/details/6979200) 

#include "stdio.h"

#include "string.h"

#include "openssl/ssl.h"

#include "openssl/bio.h"

#include "openssl/err.h"

#pragma comment(lib, "WS2_32.lib")

#pragma comment(lib, "libeay32.lib")

#pragma comment(lib, "ssleay32.lib")

//获取服务器证书

int GetSrvCert(SSL * ssl, X509 ** pCert)

{

    int rv = -1;

    if(ssl == NULL)

 {

  return rv;

 }

    rv = SSL_get_verify_result(ssl);

    *pCert = SSL_get_peer_certificate(ssl);

    return rv;

}

//验证证书的合法性

int VerifyCert(X509 * pCert, const char * hostname)

{

    char commonName [512] = {0};

    X509_NAME * name = NULL;

    if(pCert == NULL || hostname == NULL)

 {

  return -1;

 }

    //获取commonName

    name = X509_get_subject_name(pCert);

    X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);

    fprintf(stderr, "VerifyCert - Common Name on certificate: %s\n", commonName);

    if(strcmp(commonName, hostname) == 0)

 {

  return 1;

 }

    else

 {

  return 0;

 }

}

int main()

{

    BIO *bio = NULL;

    SSL *ssl = NULL;

    SSL_CTX *ctx = NULL;

    X509 *pCert = NULL;

    int nRead = 0;

 int nTotalLen = 0;

    char szHttpReq[255] = "GET / HTTP/1.1\r\nHost:
www.jinhill.com\r\nConnection: Close\r\n\r\n";

    char szResp[1024] = {0};

    //初始化SSL库

 SSL_library_init();

 

    ERR_load_BIO_strings();

    SSL_load_error_strings();

 //添加SSL握手时所有支持的算法

    OpenSSL_add_all_algorithms();

 //设置客户端使用的SSL版本

 SSL_METHOD* sslMethod = (SSL_METHOD*)SSLv3_client_method();

 //创建SSL上下文环境 每个进程只需维护一个SSL_CTX结构体

 ctx = SSL_CTX_new(sslMethod);

    //加载受信任的根证书

    if(! SSL_CTX_load_verify_locations(ctx, "JinhillRootCA.cer", NULL))

    {

        fprintf(stderr, "Error loading trust store\n");

        ERR_print_errors_fp(stderr);

        SSL_CTX_free(ctx);

        return 0;

    }

    //设置证书密码

 SSL_CTX_set_default_passwd_cb_userdata(ctx, "1234");

 //读取证书文件

 SSL_CTX_use_certificate_file(ctx,"cb.crt",SSL_FILETYPE_PEM);

 //读取密钥文件

 SSL_CTX_use_PrivateKey_file(ctx,"cb.key",SSL_FILETYPE_PEM);

 //验证密钥是否与证书一致

 SSL_CTX_check_private_key(ctx);

    bio = BIO_new_ssl_connect(ctx);

    BIO_get_ssl(bio, &ssl);

 //设备SSL连接模式自动重试

    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

 //建议连接

    BIO_set_conn_hostname(bio, "www.jinhill.com:443");

    fprintf(stderr, "Connecting to host www.jinhill.com\n");

    if(BIO_do_connect(bio) <= 0)

    {

        fprintf(stderr, "Error attempting to connect\n");

        ERR_print_errors_fp(stderr);

        BIO_free_all(bio);

        SSL_CTX_free(ctx);

        return 0;

    }

    fprintf(stderr, "Retrieving peer certificate\n");

 //获取服务器证书

    if(GetSrvCert(ssl, &pCert) != X509_V_OK)

    {

        fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl));

        BIO_free_all(bio);

        SSL_CTX_free(ctx);

        return 0;

    }

    //校验服务器证书

    fprintf(stderr, "Validating peer certificate\n");

    if(! VerifyCert(pCert, "www.jinhill.com"))

    {

        fprintf(stderr, "Hostname and Common Name do not match\n");

        BIO_free_all(bio);

        SSL_CTX_free(ctx);

        return 0;

    }

 //发送HTTP请求

    fprintf(stderr, "Sending szHttpReq\n");

    BIO_write(bio, szHttpReq, strlen(szHttpReq));

 //读取HTTP响应

    fprintf(stderr, "Reading response\n");

    nTotalLen = 0;

    while(1)

    {

        nRead = BIO_read(bio, szResp, 1024);

        if(nRead <= 0)

  {

   break;

  }

        szResp[nRead] = 0;

  nTotalLen += nRead;

        printf("%s", szResp);

    }

    printf("\nTotal bytes read: %i\n", nTotalLen);

 //关闭连接

    BIO_free_all(bio);

    SSL_CTX_free(ctx);

    return 0;

}

 源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息