openssl实例

/server.c

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#include <unistd.h>

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

#define TEST_SSL_SERVER

#ifdef TEST_SSL_SERVER
#define Time_Out_Interval 10

SSL_CTX *ctx;

char sCaKeyDir[1024] = { 0 };

char *GetExePath(char *Buffer)
{
    int count=0;
    int MAXBUFSIZE = 1024;
    Buffer[count] = '\0';
    count = readlink("/proc/self/exe", Buffer, MAXBUFSIZE);
    if (count < 0 || count >= MAXBUFSIZE)
    {
        return NULL;
    }
    Buffer[count] = '\0';
    count = strrchr(Buffer,'/')-Buffer+1;
    Buffer[count] = '\0';
    return Buffer;
}

int MySSL_Init( )
{
    char sCaPath[1024] =  { 0 }, sKeyPath[1024] = { 0 };
    SSL_library_init();

    OpenSSL_add_all_algorithms();

    SSL_load_error_strings();

    ctx = SSL_CTX_new(SSLv23_server_method());

    if (ctx == NULL)
    {
        printf("Error: new ctx error!\n");
        return -1;
    }

    void tls_info_callback(const SSL *s, int where, int ret)
    {
        char   *str;
        int     w;
        /* Adapted from OpenSSL apps/s_cb.c. */
        w = where & ~SSL_ST_MASK;

        if (w & SSL_ST_CONNECT)
            str = "SSL_connect";
        else if (w & SSL_ST_ACCEPT)
            str = "SSL_accept";
        else
            str = "unknown";
        if (where & SSL_CB_LOOP)
        {
            printf("%s:%s\r\n", str, SSL_state_string_long((SSL *) s));
        }
        else if (where & SSL_CB_ALERT)
        {
            str = (where & SSL_CB_READ) ? "read" : "write";
            if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
                printf("SSL3 alert %s:%s:%s\r\n", str,
                        SSL_alert_type_string_long(ret),
                        SSL_alert_desc_string_long(ret));
        }
        else if (where & SSL_CB_EXIT)
        {
            if (ret == 0)
                printf("%s:failed in %s\r\n", str, SSL_state_string_long((SSL *) s));
            else if (ret < 0)
            {
#ifndef LOG_NON_ERROR_STATES
                switch (SSL_get_error((SSL *) s, ret))
                {
                    case SSL_ERROR_WANT_READ:
                    case SSL_ERROR_WANT_WRITE:break;
                    default:
#endif
                        printf("%s:error in %s\r\n", str, SSL_state_string_long((SSL *) s));
                        break;
#ifndef LOG_NON_ERROR_STATES
                        }
#endif
                }
        }
    }

    SSL_CTX_set_info_callback(ctx, tls_info_callback);

    GetExePath(sCaKeyDir);

    sprintf(sCaPath, "%s", sCaKeyDir);
    strcat(sCaPath, "cacert.pem");

    if (SSL_CTX_use_certificate_file(ctx, sCaPath, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        return -1;
    }

    sprintf(sKeyPath, "%s", sCaKeyDir);

    strcat(sKeyPath, "privkey.pem");
    if (SSL_CTX_use_PrivateKey_file(ctx, sKeyPath, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        return -1;
    }

    SSL_CTX_set_timeout(ctx, Time_Out_Interval);
    return 0;
}
int MyFD_Timeout(int sock, unsigned secs, unsigned usecs)
{
    struct timeval timeout;
    fd_set fd;

    FD_ZERO(&fd);
    FD_SET(sock, &fd);

    timeout.tv_sec = secs;
    timeout.tv_usec = usecs;

    return select(sock+1, NULL, &fd, NULL, &timeout);
}

size_t MySSL_Write(SSL *ssl, void *buf, size_t len)
{
    int rc;
    unsigned long err;
    char errmsg[BUFSIZ];

    rc = SSL_write(ssl, buf, len);

    if(rc <= 0)
    {
        int fd;
        int ret;

        ret = SSL_get_error(ssl, rc);
        rc = -1;

        if((fd = SSL_get_fd(ssl)) < 0)
            return -1;

        switch(ret)
        {
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                ret = MyFD_Timeout(fd, Time_Out_Interval, 0);

                if(ret == 0)
                    return -1;
                else if(ret > 0)
                    return MySSL_Write(ssl, buf, len);
                else
                    return -1;

                break;
            default:
                while((err = ERR_get_error()))
                    fputs(ERR_error_string(err, errmsg), stderr);
                return -1;
                break;
        }
    }
    else
    {
        return rc;
    }

    return 0;
}

size_t MySSL_Read(SSL *ssl, void *buf, size_t len)
{
    int rc;

    unsigned long err;
    char errmsg[BUFSIZ];

    int ret = MyFD_Timeout(SSL_get_fd(ssl), Time_Out_Interval, 0);
    if(ret <= 0)
        return ret;
    rc = SSL_read(ssl, buf, len);

    if(rc <= 0)
    {
        int fd;
        int ret;

        ret = SSL_get_error(ssl, rc);
        rc = -1;

        if((fd = SSL_get_fd(ssl)) < 0)
            return -1;

        switch(ret)
        {
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                ret = MyFD_Timeout(fd, Time_Out_Interval, 0);

                if(ret <= 0)
                    return ret;
                else
                    return MySSL_Read(ssl, buf, len);

                break;
            default:
                if((err = ERR_get_error()) != 0)
                {
                    ERR_error_string(err, errmsg);
                    printf("error:%s\n", errmsg);
                }
                return -1;
                break;
        }
    }
    else
    {
        return rc;
    }

    return 0;
}


size_t MySSL_ReadLine(SSL *s, char *vptr, size_t len)
{
    int ret;
    char c;

    vptr[0]='\0';
    do
    {
        ret = MySSL_Read(s, &c, 1);

        if(ret == -1)
            return -1;
        else if (ret==0)
            break;

        vptr[strlen(vptr)+1]='\0';
        vptr[strlen(vptr)]=c;
    } while (c!='\n' && strlen(vptr)<len);

    if (ret!=0)
        vptr[strlen(vptr)]='\0';

    return strlen(vptr);
}
#else

static int SocketSend(int nSocketFD, char *psMsg)
{
    int ret_write;

    while((ret_write = write(nSocketFD, psMsg, strlen(psMsg))) < 0 && errno == EINTR)
        ;

    if(-1 == ret_write)
    {
        return -1;
    }
    return ret_write;
}

static int SocketRead(int nSocketFD, char *psBuffer, int nBufferLen)
{
    int ret_read;
    while((ret_read = read(nSocketFD, psBuffer, nBufferLen - 1)) < 0 && errno == EINTR)
        ;

    if(-1 == ret_read)
    {
        return -1;
    }

    return ret_read;
}
#endif

static int AcceptSocket(char *psIp, int nPort)
{
    if(psIp == NULL || nPort <= 0)
        return -1;

    long nIp = inet_addr(psIp);

    int nReuseSoAddr = 1;
    uint32_t nInterfaceIp = nIp;
    uint16_t nInterfacePort = nPort;

    struct in_addr tInterfaceInAddr;
    struct sockaddr_in tServerAddrIn;

    tInterfaceInAddr.s_addr = nInterfaceIp;

    int sockTcp = socket(AF_INET, SOCK_STREAM, 0);
    if (sockTcp < 0 )
    {
        printf("scoket error\n");
        return -1;
    }

    if ( setsockopt(sockTcp, SOL_SOCKET, SO_REUSEADDR, &nReuseSoAddr, sizeof(nReuseSoAddr)) != 0 )
    {
        printf("Setsockopt error for service @ %s:%d", inet_ntoa(tInterfaceInAddr), nInterfacePort);
        return -1;
    }

    memset(&tServerAddrIn, 0x0, sizeof(tServerAddrIn));
    tServerAddrIn.sin_family = AF_INET;
    tServerAddrIn.sin_addr.s_addr = nInterfaceIp;
    tServerAddrIn.sin_port = htons(nInterfacePort);

    if (bind(sockTcp, (struct sockaddr *)(&tServerAddrIn), sizeof(tServerAddrIn)) < 0 )
    {
        printf("Bind tcp error for service @ %s:%d", inet_ntoa(tInterfaceInAddr), nInterfacePort);
        return -1;
    }

    if ( listen(sockTcp, 10) < 0 )
    {
        printf("Cannot listen on service @ %s:%d", inet_ntoa(tInterfaceInAddr), nInterfacePort);
        return -1;
    }

    struct sockaddr_in tClientAddr;
    socklen_t nSockAddrInLen = sizeof(struct sockaddr_in);

    int sockClient = accept(sockTcp, (struct sockaddr *) (&tClientAddr), &nSockAddrInLen);
    if ( -1 == sockClient )
    {

    }

    return sockClient;
}

void MyStrTrim(char *psStr)
{
    if(NULL == psStr)
        return;

    int nLen = strlen(psStr);

    while(nLen > 0)
    {
        if(*(psStr + nLen - 1) == '\r' || *(psStr + nLen - 1) == '\n')
        {
            *(psStr + nLen - 1) = '\0';
            nLen--;
        }
        else
            break;
    }
}

int main(int argc, char *argv[])
{
    char *psIp = "127.0.0.1";
    int nPort = 25;

    if(argc == 3)
    {
        psIp = argv[1];
        nPort = atoi(argv[2]);
    }

#ifdef TEST_SSL_SERVER
    if (MySSL_Init() != 0)
    {
        printf("Error: temp error");
        return 0;
    }

    SSL *sockTlsChannel;
    sockTlsChannel = SSL_new(ctx);
    if (sockTlsChannel == NULL)
    {
        printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return 0;
    }

#endif

    printf("server listen %s:%d\n", psIp, nPort);

    int sockSMTPClient = AcceptSocket(psIp, nPort);

    if(sockSMTPClient <= 0)
    {

        printf("%s\n", "AcceptSocket fail");
        return 0;
    }

#ifdef TEST_SSL_SERVER
    if (SSL_set_fd(sockTlsChannel, sockSMTPClient) != 1)
    {
        printf("SSL_set_fd Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return 0;
    }

    if (SSL_accept(sockTlsChannel) != 1)
    {
        printf("SSL_accept Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return 0;
    }

    printf("server ready to do...\n");

    while(1)
    {
        char sBuffer[1024] = { 0 };
        printf("put msg to send:\r\n");
        fgets(sBuffer, sizeof(sBuffer), stdin);
        int n = MySSL_Write(sockTlsChannel, sBuffer, strlen(sBuffer));
        MyStrTrim(sBuffer);
        printf("server send %d bytes [%d][%s]\n", n, (int)strlen(sBuffer), sBuffer);

        memset(sBuffer, 0, sizeof(sBuffer));
        n = MySSL_Read(sockTlsChannel, sBuffer, sizeof(sBuffer));
        MyStrTrim(sBuffer);
        printf("server read %d bytes [%d][%s]\n", n, (int)strlen(sBuffer), sBuffer);
    }
#else

    char sBuffer[512] = { 0 };
    int n = SocketRead(sockSMTPClient, sBuffer, 512);
    printf("server read %d bytes [%s]\n", n, sBuffer);

    sprintf(sBuffer, "%s\n", "hello i'm server!");
    n = SocketSend(sockSMTPClient, sBuffer);
    printf("server send %d bytes\n", n);
#endif
    return EXIT_SUCCESS;
}

/client.c



#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

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

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define TEST_SSL_CLIENT

#ifdef TEST_SSL_CLIENT

#define niTimeOutInterval 5

#define BUFFER_SIZE 1024

SSL_CTX *ctx;

int MySSL_Init( )
{
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    ctx = SSL_CTX_new(SSLv23_client_method());

    if (ctx == NULL)
    {
        printf("Error: new ctx error!\n");
        return -1;
    }
    void tls_info_callback(const SSL *s, int where, int ret)
    {
        char   *str;
        int     w;
        /* Adapted from OpenSSL apps/s_cb.c. */
        w = where & ~SSL_ST_MASK;

        if (w & SSL_ST_CONNECT)
            str = "SSL_connect";
        else if (w & SSL_ST_ACCEPT)
            str = "SSL_accept";
        else
            str = "unknown";
        if (where & SSL_CB_LOOP)
        {
            printf("%s:%s\r\n", str, SSL_state_string_long((SSL *) s));
        }
        else if (where & SSL_CB_ALERT)
        {
            str = (where & SSL_CB_READ) ? "read" : "write";
            if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
                printf("SSL3 alert %s:%s:%s\r\n", str,
                        SSL_alert_type_string_long(ret),
                        SSL_alert_desc_string_long(ret));
        }
        else if (where & SSL_CB_EXIT)
        {
            if (ret == 0)
                printf("%s:failed in %s\r\n", str, SSL_state_string_long((SSL *) s));
            else if (ret < 0)
            {
#ifndef LOG_NON_ERROR_STATES
                switch (SSL_get_error((SSL *) s, ret))
                {
                    case SSL_ERROR_WANT_READ:
                    case SSL_ERROR_WANT_WRITE:            /* Don't log non-error states. */break;
                    default:
#endif
                        printf("%s:error in %s\r\n", str, SSL_state_string_long((SSL *) s));
                        break;
#ifndef LOG_NON_ERROR_STATES
                        }
#endif
                }
        }
    }
    SSL_CTX_set_timeout(ctx, 5);
    return 0;
}
int MyFD_Timeout(int sock, unsigned secs, unsigned usecs)
{
    struct timeval timeout;
    fd_set fd;

    FD_ZERO(&fd);
    FD_SET(sock, &fd);

    timeout.tv_sec = secs;
    timeout.tv_usec = usecs;

    return select(sock+1, NULL, &fd, NULL, &timeout);
}

size_t MySSL_Write(SSL *ssl, void *buf, size_t len)
{
    int rc;
    unsigned long err;
    char errmsg[BUFSIZ];

    rc = SSL_write(ssl, buf, len);

    if(rc <= 0)
    {
        int fd;
        int ret;

        ret = SSL_get_error(ssl, rc);
        rc = -1;

        if((fd = SSL_get_fd(ssl)) < 0)
            return -1;

        switch(ret)
        {
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                ret = MyFD_Timeout(fd, 5, 0);

                if(ret == 0)
                    return -1;
                else if(ret > 0)
                    return MySSL_Write(ssl, buf, len);
                else
                    return -1;

                break;
            default:
                while((err = ERR_get_error()))
                    fputs(ERR_error_string(err, errmsg), stderr);

                return -1;
                break;
        }
    }
    else
    {
        return rc;
    }

    return 0;
}

size_t MySSL_Read(SSL *ssl, void *buf, size_t len)
{
    int rc;
    unsigned long err;
    char errmsg[BUFSIZ];

    int ret = MyFD_Timeout(SSL_get_fd(ssl), niTimeOutInterval, 0);
    if(ret <= 0)
        return ret;
    rc = SSL_read(ssl, buf, len);

    if(rc <= 0)
    {
        int fd;
        int ret;

        ret = SSL_get_error(ssl, rc);
        rc = -1;

        if((fd = SSL_get_fd(ssl)) < 0)
            return -1;

        switch(ret)
        {
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
                ret = MyFD_Timeout(fd, 5, 0);

                if(ret <= 0)
                    return ret;
                else
                    return MySSL_Read(ssl, buf, len);

                break;
            default:
                if((err = ERR_get_error()) != 0)
                {
                    ERR_error_string(err, errmsg);
                    printf("error:%s\n", errmsg);
                }

                return -1;
                break;
        }
    }
    else
    {
        return rc;
    }

    return 0;
}

size_t MySSL_ReadLine(SSL *s,char *vptr,size_t len)
{
    int ret;
    char c;

    vptr[0]='\0';
    do
    {
        ret = MySSL_Read(s, &c, 1);

        if(ret == -1)
            return -1;
        else if (ret==0)
            break;

        vptr[strlen(vptr)+1]='\0';
        vptr[strlen(vptr)]=c;
    } while (c!='\n' && strlen(vptr)<len);

    if (ret!=0)
        vptr[strlen(vptr)]='\0';

    return strlen(vptr);
}
#else

static int SocketSend(int nSocketFD, char *psMsg)
{
    int ret_write;

    while((ret_write = write(nSocketFD, psMsg, strlen(psMsg))) < 0 && errno == EINTR)
        ;

    if(-1 == ret_write)
    {
        return -1;
    }
    return ret_write;
}

static int SocketRead(int nSocketFD, char *psBuffer, int nBufferLen)
{
    int ret_read;
    while((ret_read = read(nSocketFD, psBuffer, nBufferLen - 1)) < 0 && errno == EINTR)
        ;

    if(-1 == ret_read)
    {
        return -1;
    }

    return ret_read;
}
#endif

static int SocketConnent(char *psIp, int nPort)
{
    if(psIp == NULL || nPort <= 0)
        return -1;

    long nIp = inet_addr(psIp);

    struct timeval tTimeOut;
    tTimeOut.tv_sec = 5;
    tTimeOut.tv_usec = 0;

    struct linger lin;
    lin.l_onoff=1;
    lin.l_linger=0;

    struct sockaddr_in inaddr;
    inaddr.sin_family = AF_INET;
    inaddr.sin_addr.s_addr = nIp;
    inaddr.sin_port = htons(nPort);

    int niSockFd = socket(AF_INET, SOCK_STREAM, 0);
    if(niSockFd == -1)
        return -1;

    setsockopt(niSockFd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger));

    int ulFlagBlock = 1;
    ioctl(niSockFd, FIONBIO, &ulFlagBlock);
    int rv = connect(niSockFd,(struct sockaddr *)&inaddr,sizeof(struct sockaddr_in));

    if(-1 == rv && errno == EINPROGRESS)
    {
        fd_set fdSet;
        FD_ZERO(&fdSet);
        FD_SET(niSockFd, &fdSet);
        if( select(niSockFd + 1, NULL, &fdSet, NULL, &tTimeOut) > 0)
        {
            int niError = 0;
            int niLenth = sizeof(int);
            getsockopt(niSockFd, SOL_SOCKET, SO_ERROR, &niError, (socklen_t *)&niLenth);
            if(niError != 0)
            {
                close(niSockFd);
                return -1;
            }
        }
    }
    else if(rv != 0 ){
        close(niSockFd);
        return -1;
    }
    //rv == 0 connect suc

    ulFlagBlock=0;
    ioctl(niSockFd, FIONBIO, &ulFlagBlock);

    setsockopt(niSockFd,SOL_SOCKET,SO_SNDTIMEO,&tTimeOut,(socklen_t)sizeof(struct timeval));
    setsockopt(niSockFd,SOL_SOCKET,SO_RCVTIMEO,&tTimeOut,(socklen_t)sizeof(struct timeval));

    return niSockFd;
}

void MyStrTrim(char *psStr)
{
    if(NULL == psStr)
        return;

    int nLen = strlen(psStr);

    while(nLen > 0)
    {
        if(*(psStr + nLen - 1) == '\r' || *(psStr + nLen - 1) == '\n')
        {
            *(psStr + nLen - 1) = '\0';
            nLen--;
        }
        else
            break;
    }
}

int main(int argc, char *argv[])
{
    char *psIp = "127.0.0.1";
    int nPort = 25;

    if(argc == 3)
    {
        psIp = argv[1];
        nPort = atoi(argv[2]);
    }

#ifdef TEST_SSL_CLIENT
    if (MySSL_Init() != 0)
    {
        printf("Error: temp error");
        return 0;
    }

    SSL *sockTlsChannel;
    sockTlsChannel = SSL_new(ctx);
    if (sockTlsChannel == NULL)
    {
        printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return 0;
    }
#endif

    int sockSMTPClient = SocketConnent(psIp, nPort);
    if(sockSMTPClient <= 0)
    {
        printf("Error: %s %s:%d\n", "scoket connent fail", psIp, nPort);
        return 0;
    }
    printf("connect to %s:%d\n", psIp, nPort);


#ifdef TEST_SSL_CLIENT
    if (SSL_set_fd(sockTlsChannel, sockSMTPClient) != 1)
    {
        printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return 0;
    }

    if(SSL_connect(sockTlsChannel) != 1)
    {
        printf("ssl connent fail\n");
        return 0;
    }

    while(1)
    {
        char sBuffer[1024] = { 0 };

        memset(sBuffer, 0, sizeof(sBuffer));
        int n = MySSL_Read(sockTlsChannel, sBuffer, sizeof(sBuffer));
        MyStrTrim(sBuffer);
        printf("client read %d bytes [%d][%s]\n", n, (int)strlen(sBuffer), sBuffer);

        printf("put msg to send:\r\n");
        fgets(sBuffer, sizeof(sBuffer), stdin);
        n = MySSL_Write(sockTlsChannel, sBuffer, strlen(sBuffer));
        MyStrTrim(sBuffer);
        printf("client send %d bytes [%d][%s]\n", n, (int)strlen(sBuffer), sBuffer);
    }

#else
    int n = SocketSend(sockSMTPClient, sBuffer);
    printf("client send %d bytes\n", n);

    memset(sBuffer, 0, BUFFER_SIZE);
    n = SocketRead(sockSMTPClient, sBuffer, BUFFER_SIZE);
    printf("client read %d bytes [%s]\n", n, sBuffer);
#endif

    return EXIT_SUCCESS;
}



其他常用代码


	///
	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
	///
	SSL_CTX_set_cipher_list(ctx, "RC4-MD5");
	///DH
	/* Set up ephemeral DH stuff */
	DH *dh_512 = NULL;
	DH *dh_1024 = NULL;
	FILE *paramfile;
	/* "openssl dhparam -out dh_param_512.pem -2 512" */
	paramfile = fopen("dh_param_512.pem", "r");
	if (paramfile) {
		dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
		fclose(paramfile);
	}
	/* "openssl dhparam -out dh_param_1024.pem -2 1024" */
	paramfile = fopen("dh_param_1024.pem", "r");
	if (paramfile) {
	dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
		fclose(paramfile);
	}
	SSL_CTX_set_tmp_dh(ctx, dh_512);
	SSL_CTX_set_tmp_dh(ctx, dh_1024);


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值