OpenSSL客户端验证 - 需要客户端验证要求

时间:2013-07-01 16:03:37

标签: c++ linux openssl x509certificate x509

我有一个C tcp客户端,目前使用SSLV3

需要有关我缺少什么以及我需要在客户端做些什么的指导

我仍然不太清楚实施并尝试阅读文档和理解 要求人们展示一些亮点 (从原始代码中删除了很多东西)

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include "socketApp.h"
#include "stdio.h"
#include "string.h"
#include "functions.h"
#include "logger.h"
#include <errno.h>
#include <fcntl.h>

#include <malloc.h>
#include <resolv.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define TCP_KEEPALIVE 0x2
fd_set readSet, actualReadSet;
static int xSocket,ySocket,zSocket;
static char debugBuf[200];
char str[4][20] = {"INVALID","x","y","z"};
char xLogPrint=0;

#define FAIL    -1
char CertFile[] = "SocketCert.pem";
char KeyFile[] = "SocketPrivateKey.pem"; //current no key implemetation is done
SSL_CTX *ctx;
int server;
static int sslStatus;
SSL *ssl;
SSL_CTX* InitCTX(void);

int setupSSL(int server){
    SSL_library_init();
    ctx = InitCTX();
    LoadCertificates(ctx, CertFile, KeyFile);
    ssl = SSL_new(ctx);      /* create new SSL connection state */
    SSL_set_fd(ssl, server);    /* attach the socket descriptor */
    if ( SSL_connect(ssl) == FAIL ){   /* perform the connection */
        ERR_print_errors_y(stderr);
        return -1;
    }else{
        sprintf(debugBuf,"Connected with %s encryption\n", SSL_get_cipher(ssl));
        debug_log(debugBuf,TRACE_LOG);
        setSSLContext(ssl,sslStatus);
        return 0;
    }
}

int LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    if ( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 )/* set the local certificate from CertFile */
    {
        ERR_print_errors_y(stderr);
        debug_log("Certificate Load error",TRACE_LOG);
        return -1;
    }
    //printf("Server certificates:\n");
   // line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
    //printf("Subject: %s\n", line);
    /* set the private key from KeyFile (may be the same as CertFile) */
   /* if ( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0 )
    {
        ERR_print_errors_y(stderr);
        abort();
    }*/
    /* verify private key
    if ( !SSL_CTX_check_private_key(ctx) )
    {
        yrintf(stderr, "Private key does not match the public certificate\n");
        printf("abort at SSL_CTX_check_private_key");
        abort();
    }*/
    debug_log("Certificate Load success",TRACE_LOG);
    return 0;
}

SSL_CTX* InitCTX(void)
{   SSL_METHOD *method;
    SSL_CTX *ctx;
    OpenSSL_add_all_algorithms();  /* Load cryptos, et.al. */
    SSL_load_error_strings();   /* Bring in and register error messages */
    method = SSLv3_client_method();  /* Create new client-method instance */
    ctx = SSL_CTX_new(method);   /* Create new context */
    if ( ctx == NULL )
    {
        //ERR_print_errors_y(stderr);
        debug_log("SSL context load failure",TRACE_LOG);
        sprintf(debugBuf,"SYSTEM:SSL_SOCKET:creation Failed: %d %s\n",stderr,ERR_print_errors_y(stderr));
        debug_log(debugBuf,TRACE_LOG); 
        //abort();
        return ctx;
    }
    SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
    SSL_CTX_load_verify_locations(ctx,CertFile,NULL);
    return ctx;
}


int socketfdInit(void)
{
    FD_ZERO(&readSet);
    return 0;
}

int connectToServer(int server,int serverIP, int serverPort)
{
    long arg = 0;
    int *serverSock= NULL;
    int retVal, keepalive=5000,sockOpt=1;
    struct sockaddr_in localAddr, serverAddr;
    int valopt; 
    struct timeval tv;
    socklen_t opt_len; 
    int sock_err =0; 
    fd_set tempSet;
    sslStatus=getSSLEnableStatus();
    sprintf(debugBuf,"SYSTEM:x_SOCKET:sslStatus: %d \n",sslStatus);
    debug_log(debugBuf,TRACE_LOG);
    if ((*serverSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        sprintf(debugBuf,"SYSTEM:%s_SOCKET:creation Failed: %d %s\n",str[server],errno,strerror(errno));
        debug_log(debugBuf,TRACE_LOG); 
        return -1;
    }

    if (sslStatus == 1){
            retVal=setupSSL(*serverSock);
            if (retVal != 0){
                return retVal;
            }
            else{
                FD_SET(*serverSock, &readSet);
                FD_SET(*serverSock, &actualReadSet);
                return 0;
            }
        }

}   

int SendToSock( int msgLen,char *msg)
{
    int i,numBytesSent;
    int sock_err =0; 
    int sock_errl = sizeof(sock_err);
    int serverSock = 0;

    if (sslStatus == 1){
        numBytesSent = SSL_write(ssl, msg,msgLen+2);
    }
    else{
        numBytesSent = send(serverSock, msg,msgLen+2, MSG_NOSIGNAL);
    }

}
int ReceiveFromSock(char *msg,int Rxtimeout)
{

    // time val for select expiry
    struct timeval tv;
    int opt_len; // for querying getsocket opt -->value of length of result
    int sock_err=0; // placeholder integer where result is passed by getsockOpt
    int bytesRecvd=0;
    int selectRetVal;
    int tempBytesRecvd;
    int status;

    fd_set errSet ;
    int serverSock = 0;
    int len;
    char lenStr[3];
    if (sslStatus == 1){
                bytesRecvd = SSL_read(ssl, (char *)lenStr, 2);
                SSL_get_error(ssl,status);
                sprintf(debugBuf,"SYSTEM:x_SOCKET:recv: get error value %d",bytesRecvd);
                debug_log(debugBuf,TRACE_LOG);
            }else
                bytesRecvd = recv(serverSock, (char *)lenStr, 2, 0);    //receive the length in EBCDIC
    }

1 个答案:

答案 0 :(得分:0)

只是一个FYI,解决这个问题的另一种方法可能是在sslclient下运行你的C程序,它基本上类似于DJB的tcpclient,但是使用SSL - 即sslclient将产生你的程序并打开到服务器的SSL连接,并将程序的stdout传递给服务器,并将服务器的输出管道输出到程序的stdin。这样做的好处在于,只要与服务器协商SSL协议并进行实际加密,就可以让sslclient完成所有繁重工作,并且您可以专注于程序的核心功能。有关详细信息,请参阅http://www.superscript.com/ucspi-ssl/sslclient.html