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