soft

soft

ssl client

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define MAXBUF 1024 * 100
#define SERVER_CERT     "cert.pem"
#define SERVER_KEY      "key.pem"
const char *rootKey = "123456";

/*自动填入密码*/
int PemPasswdCb(char *buf, int size, int rwflag, void *password)
{
    strncpy(buf, (char *)(password), size);
    buf[size - 1] = '\0';
    return(strlen(buf));
}

/*openssl库的初始化*/
void LibSslInit()
{
    SSL_library_init(); /* 为SSL加载加密和哈希算法 */   
    OpenSSL_add_all_algorithms();/* 加载加密算法函数和单向散列算法函数 */
    SSL_load_error_strings();/* 为了更友好的报错,加载错误码的描述字符串 */
}


/*启动服务器监听*/
int StartListenServer(unsigned int portnum)
{
    struct sockaddr_in my_addr;
    int listenfd = -1;
    int reuse = 1;
    int lisnum = 5;
    int ret  = -1;
    listenfd = socket(PF_INET, SOCK_STREAM, 0);

    if (listenfd == -1) {
        perror("socket");
        exit(1);
    }
    ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    if (ret < 0) {
        printf("setsockopet error\n");
        return -1;
    }

    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(portnum);
    my_addr.sin_addr.s_addr = INADDR_ANY;

    ret = bind(listenfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr));
    if (ret == -1) {
        perror("bind");
        exit(1);
    }

    ret = listen(listenfd, lisnum);
    if (ret == -1) {
        perror("listen");
        exit(1);
    }

    return listenfd;
}

/*加载配置文件*/
void SslLoadConf(SSL_CTX *ctx)
{
    /*加载公钥证书*/
    if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /*设置私钥*/
    if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
        printf("use private key fail.\n");
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    if (!SSL_CTX_check_private_key(ctx)) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
}

/*设置密码从程序里面读取*/
void SslSetPassWd(SSL_CTX *ctx)
{
    SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)rootKey);
    SSL_CTX_set_default_passwd_cb(ctx, PemPasswdCb);
}

/*构造响应消息*/
int BuildSendBuf(char *buf, int maxBufLen)
{
    int bufLen = 0;
    char fileBuf[1024] = {0};
    int i;

    for (i = 0; i < 1024; i++)
    {
        fileBuf[i] = '1';
    }

    bufLen += snprintf(buf, maxBufLen, "%s", "HTTP/1.1 200 OK\r\n Server: Apache/1.1\r\n Content-Length:1024\r\n Content-Type:text/plain\r\n");
    bufLen += snprintf(buf + bufLen, maxBufLen, "%s", fileBuf);

    return bufLen;
}

/*处理SSL连接*/
int HandleSslConnect(SSL_CTX *ctx, int clientfd)
{
    SSL *ssl = NULL;
    char buf[MAXBUF + 1];
    int i = 0;
    int bufLen = 0;
    int ret = -1;
    int len;

    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, clientfd);
    if (SSL_accept(ssl) == -1) {
        perror("ssl accept");
        ret = -1;
        goto finish;
    }

    bzero(buf, MAXBUF + 1);
    len = SSL_read(ssl, buf, MAXBUF);
    if (len <= 0) {
        printf("read msg failed");
                    ret = -1;
        goto finish;
    }
    printf("recv buf is %s.\n", buf);

    bufLen = BuildSendBuf(buf, MAXBUF);

    len = SSL_write(ssl, buf, bufLen);
    if (len <= 0) {
        printf("msg '%s' send failed %d!\n", buf);
        ret = -1;
        goto finish;
    }
    printf("msg '%s' send success,%d byte!\n", buf, len);
    ret = 0;
finish:
    SSL_shutdown(ssl);
    SSL_free(ssl);

    return ret;
}

int main(int argc, char **argv)
{
    int listenfd = -1;
    int clientfd = -1;
    int ret = -1;
    socklen_t len;
    struct sockaddr_in my_addr;
    struct sockaddr_in their_addr;
    unsigned int myport;
    SSL_CTX *ctx;

    if (argv[1]) {
        myport = atoi(argv[1]);
    } else {
        myport = 8888;
    }

    LibSslInit();
    ctx = SSL_CTX_new(SSLv23_server_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    SslSetPassWd(ctx);
    SslLoadConf(ctx);

    listenfd = StartListenServer(myport);

    while (1) {
        len = sizeof(struct sockaddr);
        clientfd = accept(listenfd, (struct sockaddr *) &their_addr, &len);
        if (clientfd == -1) {
            perror("accept");
            continue;
        } 
        printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), clientfd);
        ret = HandleSslConnect(ctx, clientfd);
        if (ret != 0)
        {
           printf("handle ssl connect failed close clientfd %d.\n", clientfd);
        }
finish:
        close(clientfd);
    }

    close(listenfd);
    SSL_CTX_free(ctx);
    return 0;
}


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

联系我 331434376    15629529961