/Best Regards,
Sejin.
======================================================================
Client code
=======================================================================
/*
* TLS Client example
*/
#include <string>
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* define HOME to be dir for key and cert files... */
#define HOME "./CA_Client/private/"
#define MYHOME "./CA_Client/newcerts/"
/* CA file to verify client certificate */
#define CERTF HOME "CAcert.pem"
/* Certificate and Key used to identify itself to the server. */
#define MYCERTF MYHOME "newcert.pem"
#define MYKEYF MYHOME "newkey.pem"
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr);
exit(2); }
void main ()
{
int err;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
X509* server_cert;
char* str;
char tmpbuf[4];
char buf [4096];
SSL_METHOD *meth;
SSL_library_init();
SSLeay_add_ssl_algorithms();
meth = TLSv1_client_method();
SSL_load_error_strings();
CHK_SSL(err);
ctx = SSL_CTX_new (meth); CHK_NULL(ctx);
int i = 0;
if (SSL_CTX_set_options(ctx,SSL_VERIFY_PEER) <= 0 ) {
printf(" VERIFICATION ERROR\n");
exit(7);
}
//Set trusted CA certs for incomming server certificate
if (SSL_CTX_load_verify_locations(ctx,CERTF,HOME) <= 0 ) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, MYKEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr,"Private key does not match the certificate public
key\n");
exit(5);
}
/* ----------------------------------------------- */
/* Create a socket and connect to server using normal socket calls. */
sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(sd, "socket");
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
string address("192.168.174.233");
sa.sin_addr.s_addr = inet_addr (address.c_str());
//"192.168.174.233"); /* Server IP */
int port = 9540;
sa.sin_port = htons (port); /* Server Port number
*/
err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa)); CHK_ERR(err, "connect");
/* ----------------------------------------------- */
/* Now we have TCP conncetion. Start SSL negotiation. */
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
printf("Connecting....\n");
err = SSL_connect (ssl); CHK_SSL(err);
printf("Connected to server.\n");
/* Get the cipher - opt */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get server's certificate */
server_cert = SSL_get_peer_certificate (ssl);
CHK_NULL(server_cert);
if (SSL_get_verify_result(ssl) != X509_V_OK) {
printf("Server certification verification error.\n");
exit(5);
}
printf ("Server certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
free (str);
str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
free (str);
X509_free (server_cert);
/* --------------------------------------------------- */
/* DATA EXCHANGE - Send a message and receive a reply. */
err = SSL_write (ssl, "Hello World!", strlen("Hello World!"));
CHK_SSL(err);
err=SSL_peek(ssl,tmpbuf,3);
tmpbuf[err] = '\0';
printf("First 3 letters =%s \n",tmpbuf);
err = SSL_read (ssl, buf, sizeof(buf) - 1);
CHK_SSL(err);
buf[err] = '\0';
printf ("Got %d chars:'%s'\n", err, buf);
SSL_shutdown (ssl); /* send SSL/TLS close_notify */
/* Clean up. */
close (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
/* EOF - cli.cpp */
==============================================================================
Server code
================================================================================
/*
* TLS Server example
*/
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <iostream.h>
#include <openssl/rsa.h> /* SSLeay stuff */
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* define HOME to be dir for key and cert files... */
#define HOME "./CA_Server/newcerts/"
#define CLIENT_HOME "./CA_Server/private/"
/* Certificate and key file to identify itself to the client */
#define CERTF HOME "newcert.pem"
#define KEYF HOME "newkey.pem"
/* CA file used to verify client certificate */
#define CLIENT_CERTF CLIENT_HOME "CAcert.pem"
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr);
exit(2); }
static int verify_callback(int ok, X509_STORE_CTX *ctx) {
char *s,buf[256];
s =
X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,256);
if (s!=NULL) {
cout << "Depth = " << ctx->error_depth << " " << buf << endl;
}
else
cout << "X509_NAME_oneline returned NULL. " << endl;
exit(0);
}
void main ()
{
int err;
int listen_sd;
int sd;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
size_t client_len;
SSL_CTX* ctx;
SSL* ssl;
X509* client_cert;
char* str;
char buf [4096];
SSL_METHOD *meth;
// A method to initialize global data
SSL_library_init();
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = TLSv1_server_method();
ctx = SSL_CTX_new (meth);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(2);
}
if (SSL_CTX_set_options(ctx,SSL_VERIFY_PEER) <= 0) {
printf(" VERIFICATION ERROR\n");
exit(6);
}
if (SSL_CTX_load_verify_locations(ctx, CLIENT_CERTF,CLIENT_HOME) <= 0)
{
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr,"Private key does not match the certificate public
key\n");
exit(5);
}
/*
SSL_CTX_set_verify(ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
verify_callback);
printf("Callback function for verification error is set.\n");
*/
/* ----------------------------------------------- */
/* Prepare TCP socket for receiving connections */
listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd,
"socket");
printf("Socket created....\n");
memset (&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
int port = 9540;
string address("192.168.174.233");
sa_serv.sin_addr.s_addr = inet_addr(address.c_str()); //INADDR_ANY;
sa_serv.sin_port = htons (port); /* Server Port number
*/
err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv)); CHK_ERR(err, "bind");
printf("Socket bound to service...\n");
/* Receive a TCP connection. */
err = listen (listen_sd, 5); CHK_ERR(err,
"listen");
client_len = sizeof(sa_cli);
printf("Listening....\n");
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
printf("Connection accepted.\n");
CHK_ERR(sd, "accept");
close (listen_sd);
cout << "Remote IP address = " << inet_ntoa(sa_cli.sin_addr) << endl;
cout << "Remote port number = " << ntohs(sa_cli.sin_port) << endl;
/* ----------------------------------------------- */
/* TCP connection is ready. Do server side SSL. */
printf("Initiating ssl server process..\n");
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
printf("Calling SSL_accept..\n");
err = SSL_accept (ssl); CHK_SSL(err);
/* Get the cipher - opt */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get client's certificate - opt */
client_cert = SSL_get_peer_certificate (ssl);
if (SSL_get_verify_result(ssl) != X509_V_OK) {
printf("Client certification verification error.\n");
exit(6);
}
if (client_cert != NULL) {
printf ("Client certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
free (str);
/* We could do all sorts of certificate verification stuff here
before
deallocating the certificate. */
X509_free (client_cert);
} else
printf ("Client does not have certificate.\n");
/* DATA EXCHANGE - Receive message and send reply. */
err = SSL_read (ssl, buf, sizeof(buf) - 1);
CHK_SSL(err);
buf[err] = '\0';
printf ("Got %d chars:'%s'\n", err, buf);
err = SSL_write (ssl, "I hear you.", strlen("I hear you."));
CHK_SSL(err);
/* Clean up. */
close (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
/* EOF - serv.cpp */
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org
Well there's something that immediately strikes me as suspicious:
>
> static int verify_callback(int ok, X509_STORE_CTX *ctx) {
>
> char *s,buf[256];
>
> s =
> X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,256);
> if (s!=NULL) {
> cout << "Depth = " << ctx->error_depth << " " << buf << endl;
> }
> else
> cout << "X509_NAME_oneline returned NULL. " << endl;
> exit(0);
> }
>
Is this doing what I think its doing? Bombing out with exit(0)
unconditionally?
Steve.
--
Dr Stephen N. Henson. http://www.drh-consultancy.demon.co.uk/
Personal Email: she...@drh-consultancy.demon.co.uk
Senior crypto engineer, Gemplus: http://www.gemplus.com/
Core developer of the OpenSSL project: http://www.openssl.org/
Business Email: stephen...@gemplus.com PGP key: via homepage.
You're right, it shouldn't.
But my problem is how to generate/verify the client certificate if there's any
difference from the server side certificate.
Even without setting the verify funcition, it still has the same problem.
Thanks.
/Best regards,
Sejin
Dr S N Henson wrote:
> Sejin Choi wrote:
> >
> > Ah, this is just a sample code just to see if it's working. This is not the
> > full version of application code. :)
> > While making the sample code, I think I made a mistake to put exit code there.
> >
> > You're right, it shouldn't.
> > But my problem is how to generate/verify the client certificate if there's any
> > difference from the server side certificate.
> > Even without setting the verify funcition, it still has the same problem.
> > Thanks.
> >
>
> I didn't spot anything else obvious. Have you tried using the s_client
> and s_server OpenSSL applications and seeing if the client certificate
> is visible?