// SSL_Client.c // // Copyright 2009 Kim Sung-tae // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, // MA 02110-1301, USA. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 7921 #define SERVER_ADDRESS "127.0.0.1" int main(int argc, char** argv) { char *server_name = SERVER_ADDRESS; unsigned short port = PORT; unsigned int addr; struct sockaddr_in server_add; struct hostent *host; int conn_socket; int socket_type = SOCK_STREAM; int retval; char *retString = NULL; const char *currentCipher; char buffer[1000]; char message[100] = "이것은 클라이언트가 보내는 메시지입니다."; // SSL 구조체 생성 SSL_METHOD *meth; SSL_CTX *ctx; SSL *ssl; X509 *server_cert; BIO *errBIO; if((errBIO = BIO_new(BIO_s_file())) != NULL) BIO_set_fp(errBIO, stderr, BIO_NOCLOSE|BIO_FP_TEXT); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); meth = SSLv3_method(); ctx = SSL_CTX_new(meth); if(ctx == NULL) { BIO_printf(errBIO, "SSL_CTX 생성 에러"); ERR_print_errors(errBIO); exit(1); } // 서버 이름이 알파벳인 DNS로 되어 있을 경우 if(isalpha(server_name[0])) { host = gethostbyname(server_name); } // 서버 이름이 IP 로 되어 있을 경우 else { addr = inet_addr(server_name); host = gethostbyaddr((char *)&addr, 4, AF_INET); } if(host == NULL) { fprintf(stderr, "알 수 없는 주소[%s] 입니다!\n", server_name); exit(1); } memset(&server_add, 0, sizeof(server_add)); memcpy(&(server_add.sin_addr), host->h_addr, host->h_length); server_add.sin_family = host->h_addrtype; server_add.sin_port = htons(port); conn_socket = socket(AF_INET, socket_type, 0); if(conn_socket < 0) { fprintf(stderr, "소켓 생성 에러!\n"); exit(1); } printf("[%s] 서버에 연결중...\n", server_name); if(connect(conn_socket, (struct sockaddr*)&server_add, sizeof(server_add)) == -1) { fprintf(stderr, "connect 에러!\n"); exit(1); } // 세션 키를 만들기 위한 랜덤 수를 위한 Seed 공급 printf("랜덤 수 생성중...\n"); RAND_status(); printf("랜덤 수 생성 완료!\b"); ssl = SSL_new(ctx); if(ssl == NULL) { BIO_printf(errBIO, "SSL 생성 에러!\n"); ERR_print_errors(errBIO); exit(1); } SSL_set_fd(ssl, conn_socket); retval = SSL_connect(ssl); if(retval == -1) { BIO_printf(errBIO, "SSL connect 에러!\n"); ERR_print_errors(errBIO); exit(1); } currentCipher = SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)); printf("SSL 연결, 사용 알고리즘 파라메터: [%s]\n", currentCipher); server_cert = SSL_get_peer_certificate(ssl); if(server_cert == NULL) { BIO_printf(errBIO, "서버 인증서를 받을 수 없음."); ERR_print_errors(errBIO); exit(1); } printf("Server certificate:\n"); retString = NULL; // 주체의 DN을 문자열로 얻음 retString = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0); if(retString == NULL) { BIO_printf(errBIO, "서버 인증서에서 주체의 DN을 읽을 수 없음."); ERR_print_errors(errBIO); exit(1); } printf("\t subject: %s\n", retString); free(retString); // 발급자의 DN을 문자열로 얻음 retString = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0); if(retString == NULL) { BIO_printf(errBIO, "서버 인증서에서 발급자의 DN을 읽을 수 없음."); ERR_print_errors(errBIO); exit(1); } printf("\t issuer: %s\n", retString); free(retString); X509_free(server_cert); retval = SSL_write(ssl, "hi!!_from client", strlen("hi!!_from client")); if(retval == -1) { BIO_printf(errBIO, "SSL write 에러!\n"); ERR_print_errors(errBIO); exit(1); } retval = SSL_read(ssl, buffer, sizeof(buffer) - 1); if(retval == -1) { BIO_printf(errBIO, "SSL read 에러!\n"); ERR_print_errors(errBIO); exit(1); } buffer[retval] = '\0'; printf("서버로부터 데이터 전송: [%s], 길이:%d\n", buffer, retval); SSL_shutdown(ssl); close(conn_socket); SSL_free(ssl); SSL_CTX_free(ctx); return 0; }