// SSL_Client.c
//
//
Copyright 2009 Kim Sung-tae <pchero21@gmail.com>
//
//
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <arpa/inet.h>
#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;
}
SSL_Client.c


