0

我有一个 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
    }
4

1 回答 1

0

仅供参考,解决此问题的另一种方法可能是在 sslclient 下运行您的 C 程序,它的工作原理基本上类似于 DJB 的 tcpclient,但使用 SSL - 即 sslclient 将生成您的程序并打开与服务器的 SSL 连接,并通过管道传输您的程序的标准输出到服务器,并将服务器的输出通过管道传输到程序的标准输入。这样做的好处是您可以让 sslclient 承担所有繁重的工作,例如与服务器协商 SSL 协议并进行实际加密,并且您可以专注于程序的核心功能。有关详细信息,请参阅http://www.superscript.com/ucspi-ssl/sslclient.html

于 2013-07-01T17:42:35.320 回答