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()
'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 |