secure socket programming
프로그래밍/C++ 2015. 8. 11. 14:00 |secure socket programming
server
Collapse source
//SSL-Server.c #include <stdio.h> #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 = SSLv23_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= "<html><body><pre>%s</pre></body></html>\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 <portnum>\n" , strings[0]); exit (0); } SSL_library_init(); portnum = strings[1]; ctx = InitServerCTX(); /* initialize SSL */ LoadCertificates(ctx, "mycert.pem" , "mycert.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 */ return 0; } |
컴파일 :
gcc -Wall -o server server.c -lssl -lcrypto |
client
Collapse source
#include <stdio.h> #include <errno.h> #include <unistd.h> #include <malloc.h> #include <string.h> #include <sys/socket.h> #include <resolv.h> #include <netdb.h> #include <openssl/ssl.h> #include <openssl/err.h> #define FAIL -1 int OpenConnection( const char *hostname, int port) { int sd; struct hostent *host; struct sockaddr_in addr; if ( (host = gethostbyname(hostname)) == NULL ) { perror (hostname); abort (); } 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 = *( long *)(host->h_addr); if ( connect(sd, ( struct sockaddr*)&addr, sizeof (addr)) != 0 ) { close(sd); perror (hostname); abort (); } return sd; } SSL_CTX* InitCTX( void ) { SSL_METHOD *method; SSL_CTX *ctx; OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */ SSL_load_error_strings(); /* Bring in and register error messages */ method = SSLv23_client_method(); /* Create new client-method instance */ ctx = SSL_CTX_new(method); /* Create new context */ if ( ctx == NULL ) { ERR_print_errors_fp(stderr); abort (); } return ctx; } void ShowCerts(SSL* ssl) { X509 *cert; char *line; cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */ 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); /* free the malloc'ed string */ line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf ( "Issuer: %s\n" , line); free (line); /* free the malloc'ed string */ X509_free(cert); /* free the malloc'ed certificate copy */ } else printf ( "No certificates.\n" ); } int main( int count, char *strings[]) { SSL_CTX *ctx; int server; SSL *ssl; char buf[1024]; int bytes; char *hostname, *portnum; if ( count != 3 ) { printf ( "usage: %s <hostname> <portnum>\n" , strings[0]); exit (0); } SSL_library_init(); hostname=strings[1]; portnum=strings[2]; ctx = InitCTX(); server = OpenConnection(hostname, atoi (portnum)); ssl = SSL_new(ctx); /* create new SSL connection state */ SSL_set_fd(ssl, server); /* attach the socket descriptor */ if ( SSL_connect(ssl) == FAIL ) /* perform the connection */ ERR_print_errors_fp(stderr); else { char *msg = "Hello???" ; printf ( "Connected with %s encryption\n" , SSL_get_cipher(ssl)); ShowCerts(ssl); /* get any certs */ SSL_write(ssl, msg, strlen (msg)); /* encrypt & send message */ bytes = SSL_read(ssl, buf, sizeof (buf)); /* get reply & decrypt */ buf[bytes] = 0; printf ( "Received: \"%s\"\n" , buf); SSL_free(ssl); /* release connection state */ } close(server); /* close socket */ SSL_CTX_free(ctx); /* release context */ return 0; } |
컴파일 :
gcc -Wall -o server client.c -lssl -lcrypto |
references:
[1] Secure programming with the OpenSSL API, Part 1: Overview of the API : http://www.ibm.com/developerworks/library/l-openssl.html
[2] Korean Version of [1] : http://hasu0707.tistory.com/153
[3] Secure Server Client using OpenSSL in C : http://simplestcodings.blogspot.kr/2010/08/secure-server-client-using-openssl-in-c.html
[4] HTTPS와 SSL 인증서 : http://opentutorials.org/course/228/4894
[5] SSL/TLS Programming : http://www.cs.odu.edu/~cs772/fall08/lectures/ssl_programming.pdf