본문 바로가기

Programming

OpenSSL Server Example

SSL 클라이언트의 경우 인증서와 public key 페어가 없어도 되지만 서버의 경우
public key-private key 페어와 public key 에 대한 인증서가 필요하다.

물론 공인인증서는 어떻게 만드는지는 몰라도 유료이므로
그냥 사설인증서를 만들어서 쓰면되는데

openssl 툴설치
apt-get install openssl

openssl 라이브러리 설치(헤더파일등)
apt-get install libssl-dev


openssl 툴로 아래와같이 private key 와 public key 가 들어있는 인증서를
하나의 파일에 출력해서 만들 수 있다. 자세한 옵션은 구글링 ㄱㄱ

But before running this program you will need a Certificate which is used in this program. You can generate your own certificate using this command

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout key.pem -out mycert.pem

, where mycert.pem is the name of the Certificate file.

To run the Server
gcc -Wall -lssl -lcrypto -o ssl-server SSL-Server.c
./ssl-server 

To run the Client 
gcc -Wall -lssl -lcrypto -o ssl-client SSL-Client.c
./ssl-client 

그리고 서버에서 

method = SSLv2_server_method();  /* create new server-method instance */

ctx = SSL_CTX_new(method);   /* create new context from method */


이렇게하면 SSL v2 만 지원하게 되는데 v3 클라이언트의 연결을 받을수 없다.

SSLv23_server_method 로 해야 v3 와 v2 를 모두 지원함



//SSL-Server.c
#include "errno.h"
#include "unistd.h"
#include "malloc.h"
#include "string.h"
#include "arpa/inet.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "resolv.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

#define FAIL    -1

int OpenListener(int port)
{   int sd;
    struct sockaddr_in addr;

    sd = socket(PF_INET, SOCK_STREAM, 0);
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
        perror("can't bind port");
        abort();
    }
    if ( listen(sd, 10) != 0 )
    {
        perror("Can't configure listening port");
        abort();
    }
    return sd;
}

SSL_CTX* InitServerCTX(void)
{   SSL_METHOD *method;
    SSL_CTX *ctx;

    OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
    SSL_load_error_strings();   /* load all error messages */
    method = SSLv2_server_method();  /* create new server-method instance */
    ctx = SSL_CTX_new(method);   /* create new context from method */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
 /* set the local certificate from CertFile */
    if ( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    /* 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_fp(stderr);
        abort();
    }
    /* verify private key */
    if ( !SSL_CTX_check_private_key(ctx) )
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }
}

void ShowCerts(SSL* ssl)
{   X509 *cert;
    char *line;

    cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
    if ( cert != NULL )
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("Subject: %s\n", line);
        free(line);
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s\n", line);
        free(line);
        X509_free(cert);
    }
    else
        printf("No certificates.\n");
}

void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{   char buf[1024];
    char reply[1024];
    int sd, bytes;
    const char* HTMLecho="%s\n\n";

    if ( SSL_accept(ssl) == FAIL )     /* do SSL-protocol accept */
        ERR_print_errors_fp(stderr);
    else
    {
        ShowCerts(ssl);        /* get any certificates */
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
        if ( bytes > 0 )
        {
            buf[bytes] = 0;
            printf("Client msg: \"%s\"\n", buf);
            sprintf(reply, HTMLecho, buf);   /* construct reply */
            SSL_write(ssl, reply, strlen(reply)); /* send reply */
        }
        else
            ERR_print_errors_fp(stderr);
    }
    sd = SSL_get_fd(ssl);       /* get socket connection */
    SSL_free(ssl);         /* release SSL state */
    close(sd);          /* close connection */
}

int main(int count, char *strings[])
{   SSL_CTX *ctx;
    int server;
    char *portnum;

    if ( count != 2 )
    {
        printf("Usage: %s \n", strings[0]);
        exit(0);
    }
    SSL_library_init();

    portnum = strings[1];
    ctx = InitServerCTX();        /* initialize SSL */
    LoadCertificates(ctx, "mycert.pem", "key.pem"); /* load certs */
    server = OpenListener(atoi(portnum));    /* create server socket */
    while (1)
    {   struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL *ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);  /* accept connection as usual */
        printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);              /* get new SSL state with context */
        SSL_set_fd(ssl, client);      /* set connection socket to SSL state */
        Servlet(ssl);         /* service connection */
    }
    close(server);          /* close server socket */
    SSL_CTX_free(ctx);         /* release context */
}


root@ubuntu:/var/www/multieyes# ./relay 6666 7777
3074045576:error:140A90A1:SSL routines:SSL_CTX_new:library has no ciphers:ssl_lib.c:1768:
Aborted (core dumped)
Solution for your problem is, call the routine SSL_library_init()


'Programming' 카테고리의 다른 글

Windows7 SSDT Hooking  (6) 2013.03.06
x86 privilege level  (0) 2013.02.21
linux/windows SSL client example  (0) 2013.02.04
QEMU Detection  (0) 2013.01.28
Anti Debugging with POP SS  (0) 2013.01.28