Programming
OpenSSL Server Example
daehee87
2013. 2. 5. 22:18
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
./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()