On Thu, 16 Mar 2000, Lutz Jaenicke wrote:

Thanks to everybody helping me. As I understand it the process is:

In s_server.c s_server_verify is set to
SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE for the case I am interested in.
Then it calls SSL_CTX_load_verify_locations(ctx,CAfile,CApath)
or SSL_CTX_set_default_verify_paths(ctx)
and SSL_CTX_set_verify(ctx,s_server_verify,verify_callback).

I've added the following lines to serv.cpp:

 SSL_CTX_set_default_verify_paths(ctx);
 SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, NULL );
 
and the error it returns on failing is:

Connection from 100007f, port f04
4294401037:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no
certificate returned:d:\work\openssl\openss~1.5\ssl\s3_srvr.c:1677:

I'm using openssl.exe with the command line "openssl s_client -connect
localhost:443 -key z:\robert.key -cert z:\robert.crt" to test the server
program.

If I use openssl.exe as server, everything seems to work. The command line
I use is: "d:\work\openssl\bin>openssl.exe s_server -key z:\robert.key
-cert z:\robert.crt -accept 443 -verify 1".

Attached is the file I'm playing with.. A modified version of serv.cpp for
Borland C++ Builder 4.0.

Any ideas would really be apreciated.

Robert Sandilands

> From: Lutz Jaenicke <[EMAIL PROTECTED]>
> Subject: Re: demos/ssl/serv.cpp
> 
> On Thu, Mar 16, 2000 at 11:19:16AM +0200, [EMAIL PROTECTED] wrote:
> > On Wed, 15 Mar 2000, Wade L. Scholine wrote:
> > > From: Wade L. Scholine <[EMAIL PROTECTED]>
> > > To: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
> > > Subject: RE: demos/ssl/serv.cpp
> > 
> > client_cert = SSL_get_certificate( ssl ); 
> > 
> > in serv.cpp always fails. I want to know how can I make that one line
> > work?
> 
> Again, Wade already gave you the necessary answer. The client will only
> send the certificate to the server, _if_ explicitely asked to do so
> during handshake. The default is to not ask for a client certificate.
> On the server you must change the behaviour with the
> SSL_[CTX_]set_verify() call and the options SSL_VERIFY_PEER etc options.
> Please check apps/s_server.c as an example on how the call is used and
> grep for s_server_verify to see the setting of the options.
> 
> Only then you can later access the client certificate. Or to say it the
> other way round, without setting the verify option, this example should
> never have shown a client certificate to anybody.



#pragma hdrstop

#include <condefs.h>

//---------------------------------------------------------------------------

USELIB("..\..\openssl\lib\ssleay32.lib");

USELIB("..\..\openssl\lib\libeay32.lib");

//---------------------------------------------------------------------------

/* serv.cpp  -  Minimal ssleay server for Unix

   30.9.1996, Sampo Kellomaki <[EMAIL PROTECTED]> */





/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b

   Simplified to be even more minimal

   12/98 - 4/99 Wade Scholine <[EMAIL PROTECTED]> */



#include <stdio.h>

#include <stdlib.h>

#include <memory.h>

#include <errno.h>

#ifndef __WIN32__

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#else

#include <windows.h>

#endif

#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>

#include <openssl/rand.h>



/* define HOME to be dir for key and cert files... */

#ifdef __WIN32__

#define HOME "z:\\"

/* Make these what you want for cert & key files */

#define CERTF  HOME "robert.crt"

#define KEYF  HOME  "robert.key"

#else

#define HOME "./"

/* Make these what you want for cert & key files */

#define CERTF  HOME "foo-cert.pem"

#define KEYF  HOME  "foo-cert.pem"

#endif





#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 listen_sd;

  int sd;

  struct sockaddr_in sa_serv;

  struct sockaddr_in sa_cli;

  int client_len;

  SSL_CTX* ctx;

  SSL*     ssl;

  X509*    client_cert;

  char*    str;

  char     buf [4096];

  SSL_METHOD *meth;

  

  /* SSL preliminaries. We keep the certificate and key with the context. */



  RAND_load_file( _argv[0], 64*1024 );

  SSL_load_error_strings();

  SSLeay_add_ssl_algorithms();

  meth = SSLv23_server_method();

  ctx = SSL_CTX_new (meth);

  if (!ctx) {

    ERR_print_errors_fp(stderr);

    exit(2);

  }

  

  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_depth( ctx, 1 );

 SSL_CTX_set_default_verify_paths(ctx);

 SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, NULL );

   /* ----------------------------------------------- */

  /* Prepare TCP socket for receiving connections */



#ifdef __WIN32__

 WORD VersionRequested;

 WSADATA wsaData;



 VersionRequested=MAKEWORD(1,1);

 err=WSAStartup( VersionRequested, &wsaData );

 if (err!=0) return;

 if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )

   {

    WSACleanup();

    printf( "WSAStartup: Wrong version.\n" );

    return;

   }

#endif

  listen_sd = socket (AF_INET, SOCK_STREAM, 0);

  CHK_ERR(listen_sd, "socket");



  memset (&sa_serv, '\0', sizeof(sa_serv));

  sa_serv.sin_family      = AF_INET;

  sa_serv.sin_addr.s_addr = INADDR_ANY;

  sa_serv.sin_port        = htons (443);          /* Server Port number */



  err = bind(listen_sd, (struct sockaddr*) &sa_serv,

             sizeof (sa_serv));                   CHK_ERR(err, "bind");

             

  /* Receive a TCP connection. */

             

  err = listen (listen_sd, 5);                    CHK_ERR(err, "listen");

  

  client_len = sizeof(sa_cli);

  sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);

  CHK_ERR(sd, "accept");

#ifndef __WIN32__

  close (listen_sd);

#else

  closesocket( listen_sd );

#endif

  printf ("Connection from %lx, port %x\n",

          sa_cli.sin_addr.s_addr, sa_cli.sin_port);

  

  /* ----------------------------------------------- */

  /* TCP connection is ready. Do server side SSL. */



  ssl = SSL_new (ctx);

  CHK_NULL(ssl);

  SSL_set_fd (ssl, sd);

  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 (note: beware of dynamic allocation) - opt */



  client_cert = SSL_get_peer_certificate (ssl);

  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. */



#ifndef __WIN32__

  close (sd);

#else

  closesocket( sd );

#endif

  SSL_free (ssl);

  SSL_CTX_free (ctx);

#ifdef __WIN32__

   WSACleanup();

#endif

}

/* EOF - serv.cpp */

Reply via email to