Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Client certificate question

15 views
Skip to first unread message

Sejin Choi

unread,
Feb 22, 2002, 1:55:10 PM2/22/02
to
Hi, all.
Thanks for all the advices you all gave me on my previous question
regarding client certficate question.
I've attached simple client/server code I've been using to establish SSL
connection between TCP/IP client/server application program.
Client side verified server certificate without any problem, however the
server's error message indicates that the client doesn't have
certificate.
Coult you please take a moment to read my simple client/server code and
give me help to find what the problem is?
I've been struggling with this for a long time, but unfortunately I
don't even have a clue why this short,simple code is not working both
way.
I'd very,very much appreciate it if you could give me any hint to solve
the problem. :)
Thanks and have a great weekend!

/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

Dr S N Henson

unread,
Feb 22, 2002, 2:18:33 PM2/22/02
to
Sejin Choi wrote:
>
> Hi, all.
> Thanks for all the advices you all gave me on my previous question
> regarding client certficate question.
> I've attached simple client/server code I've been using to establish SSL
> connection between TCP/IP client/server application program.
> Client side verified server certificate without any problem, however the
> server's error message indicates that the client doesn't have
> certificate.
> Coult you please take a moment to read my simple client/server code and
> give me help to find what the problem is?
> I've been struggling with this for a long time, but unfortunately I
> don't even have a clue why this short,simple code is not working both
> way.
> I'd very,very much appreciate it if you could give me any hint to solve
> the problem. :)
> Thanks and have a great weekend!
>

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.

Sejin Choi

unread,
Feb 22, 2002, 2:28:15 PM2/22/02
to
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.

Sejin Choi

unread,
Feb 22, 2002, 6:09:45 PM2/22/02
to
Hi again.
Thanks for your tip.
As you recommended, I took a look at the s_server code, and I found out that
SSL_CTX_set_client_CA_list() function call was missing from my server code.
So I added it, and it worked beautifully.
I really appreciate your help.
Have a great weekend. (Thanks to you, I can enjoy my weekend without worrying about
SSL). :)

/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?

0 new messages