MDGSF Software Engineer

[openssl] Simple tcp server

2017-01-11
mdgsf

Generate private key and cacert.pem

To generate RSA private key, 2048 bit. openssl genrsa -out privatekey.pem

To generate RSA public key openssl rsa -in privatekey.pem -pubout -out publickey.pem

chage private key to pkcs8 format: openssl pkcs8 -topk8 -inform PEM -in privatekey.pem -outform PEM -nocrypt

To create a hex-encoded message digest of a file: openssl dgst -md5 -hex file.txt

To sign a file using SHA-256 with binary file output: openssl dgst -sha256 -sign privatekey.pem -out signature.sign file.txt

To verify a signature: openssl dgst -sha256 -verify publickey.pem -signature signature.sign file.txt

Code

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

#define IP "127.0.0.1"
#define PORT 8383
#define FILE_CACERT "cacert.pem"
#define FILE_PRIVATE_KEY "privatekey.pem"

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

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

    if(SSL_CTX_use_certificate_file(ctx, FILE_CACERT,  SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    if(SSL_CTX_use_PrivateKey_file(ctx, FILE_PRIVATE_KEY, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

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

    int iSockFD = socket(AF_INET, SOCK_STREAM, 0);
    if(iSockFD == -1) {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in stServerAddr;
    memset(&stServerAddr, 0, sizeof(stServerAddr));
    stServerAddr.sin_family = AF_INET;
    stServerAddr.sin_port = htons(PORT);
    stServerAddr.sin_addr.s_addr = inet_addr(IP);

    if(bind(iSockFD, (struct sockaddr*)&stServerAddr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    if(listen(iSockFD, 5) == -1) {
        perror("listen");
        exit(1);
    }

    while (1)
    {
        socklen_t iLen = sizeof(struct sockaddr);
        struct sockaddr_in stClientAddr;
        int iNewFD = accept(iSockFD, (struct sockaddr*)&stClientAddr, &iLen);
        if(iNewFD == -1) {
            perror("accept");
            exit(1);
        }
        printf("%s:%d, socket %d\n",
                inet_ntoa(stClientAddr.sin_addr),
                ntohs(stClientAddr.sin_port),
                iNewFD);

        SSL * ssl = SSL_new(ctx);
        SSL_set_fd(ssl, iNewFD);
        if(SSL_accept(ssl) == -1) {
            perror("SSL_accept");
            close(iNewFD);
            break;
        }

        char acBuf[BUFSIZ] = {0};
        strcpy(acBuf, "server->client");

        sleep(2);

        iLen = SSL_write(ssl, acBuf, strlen(acBuf));
        if(iLen <= 0) {
            printf("SSL_write failed\n");
            goto finish;
        }

        memset(acBuf, 0, sizeof(acBuf));
        iLen = SSL_read(ssl, acBuf, sizeof(acBuf));
        if(iLen <= 0) {
            printf("SSL_read failed\n");
        } else {
            printf("SSL_read success, acBuf = %s\n", acBuf);
        }


finish:
        SSL_shutdown(ssl);
        SSL_free(ssl);
        close(iNewFD);
    }

    close(iSockFD);
    SSL_CTX_free(ctx);

    return 0;
}

weixingongzhonghao

Comments

Content