// client.cpp : application console
//
#include "stdafx.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define CA_FILE "C:\\TEMP\\openssl\\CA_CDN.crt"
#define CA_DIR NULL
//#define CA_FILE NULL
//#define CA_DIR "C:\\temp\\openssl"
#define CLIENT_CRT "C:\\TEMP\\openssl\\NET208WEB001_crt.pem"
//#define CLIENT_PVK "C:\\temp2\\cert\\client1_ca2_pvk.pem"
static char pass
[]=
"MjYxQUNERjE=";
//
// insérer Ws2_32.lib dans Link>General>Library Modules
// insérer C:\OpenSSL\include dans C/C++>PreProcessor>Additional include directories
// insérer C:\OpenSSL\out32.dbg Link>Input>Additional library path:
// C/C++>Code Generation>Use Runtime library>Debug Multithread DLL
//
#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); }
#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "libeay32.lib")
static int password_cb
(char *buf,
int num,
int rwflag,
void *userdata
)
{
if(num<strlen
(pass
)+
1)
return(0);
strcpy
(buf,pass
);
return(strlen
(pass
));
}
void PrintSSLError
(){
int sslerror = ERR_get_error
();
char error_buffer
[120];
ERR_error_string
(sslerror, error_buffer
);
printf("%s",error_buffer
);
}
int verify_callback
(int ok, X509_STORE_CTX *store
)
{
char data
[256];
printf("verify_callback\r\n");
if (!ok
)
{
X509 *cert = X509_STORE_CTX_get_current_cert
(store
);
int depth = X509_STORE_CTX_get_error_depth
(store
);
int err = X509_STORE_CTX_get_error
(store
);
//printf("-Error with certificate at depth: %i\n", depth);
//X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
//printf(" issuer = %s\n", data);
//X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
//printf(" subject = %s\n", data);
//printf("err %i:%s\n", err, X509_verify_cert_error_string(err));
PrintSSLError
();
}
return ok;
}
int main
(int argc,
char* argv
[])
{
WSADATA wsaData;
SOCKET sd;
struct sockaddr_in sa;
hostent* remoteHost;
int err;
char buf
[4096];
SSL_CTX* ctx;
SSL* ssl;
X509* server_cert;
SSL_METHOD *meth;
X509_STORE *store;
X509_LOOKUP *lookup;
X509_STORE_CTX *verify_ctx;
X509 *cert;
FILE *fp=
NULL;
//-----------------------------------------------
// Initialize Winsock
WSAStartup
(MAKEWORD
(2,
2), &wsaData
);
sd = socket
(AF_INET, SOCK_STREAM,
0); CHK_ERR
(sd,
"socket");
memset
(&sa,
'\0',
sizeof(sa
));
sa.
sin_family = AF_INET;
//sa.sin_addr.s_addr = inet_addr ("172.31.198.15"); /* Server IP */
remoteHost = gethostbyname
("sec030dev146");
sa.
sin_addr.
s_addr = *
((u_long*
)remoteHost->h_addr_list
[0]);
sa.
sin_port= htons
(2907);
/* Server Port number */
err = connect
(sd,
(struct sockaddr*
) &sa,
sizeof(sa
));
CHK_ERR
(err,
"connect");
// INIT
SSL_library_init
();
SSLeay_add_ssl_algorithms
();
meth = SSLv3_client_method
();
SSL_load_error_strings
();
ctx = SSL_CTX_new
(meth
);
CHK_NULL
(ctx
);
printf("SSL_CTX_load_verify_locations\r\n");
if (SSL_CTX_load_verify_locations
(ctx, CA_FILE, CA_DIR
) !=
1)
printf("Error loading CA file and/or directory");
//if(!(SSL_CTX_use_certificate_file(ctx,"c:\\client2_crt.pem",SSL_FILETYPE_PEM))){
// printf("Couldn't read certificate file");
// int sslerror = ERR_get_error();
// char error_buffer[120];
// ERR_error_string(sslerror, error_buffer);
// printf("%s",error_buffer);
//}
if(!SSL_CTX_use_certificate_chain_file
(ctx, CLIENT_CRT
)){
printf("Couldn't read certificate file");
int sslerror = ERR_get_error
();
char error_buffer
[120];
ERR_error_string
(sslerror, error_buffer
);
printf("%s",error_buffer
);
}
printf("SSL_CTX_set_default_passwd_cb\r\n");
SSL_CTX_set_default_passwd_cb
(ctx,password_cb
);
printf("SSL_CTX_use_PrivateKey_file\r\n");
//if(!(SSL_CTX_use_PrivateKey_file(ctx,CLIENT_PVK,SSL_FILETYPE_PEM))){
if(!
(SSL_CTX_use_PrivateKey_file
(ctx,CLIENT_CRT,SSL_FILETYPE_PEM
))){
printf("Couldn't read private key file");
}
SSL_CTX_set_verify
(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,verify_callback
);
CHK_SSL
(err
);
// first read the client certificate
printf("opening client certificate ...\r\n");
if ((fp = fopen
(CLIENT_CRT,
"r")) ==
NULL){
printf("Error reading client certificate file");
return 0;
}
printf("PEM_read_X509...\r\n");
cert = PEM_read_X509
(fp,
NULL,
NULL,
NULL);
//if ((cert = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL){
// printf("Error reading client certificate in file");
// return 0;
//}
fclose
(fp
);
printf("creating store...");
if (!
(store = X509_STORE_new
())){
printf("error initialize store certificat");
return 1;
}
X509_STORE_set_verify_cb_func
(store, verify_callback
);
printf("reading CA ...");
if (X509_STORE_load_locations
(store, CA_FILE, CA_DIR
) !=
1){
PrintSSLError
();
printf("Error loading the CA file or directory");
}
if (X509_STORE_set_default_paths
(store
) !=
1)
printf ("Error loading the system-wide CA certificates");
if (!
(lookup = X509_STORE_add_lookup
(store, X509_LOOKUP_file
())))
printf ("Error creating X509_LOOKUP object");
//if (X509_load_crl_file (lookup, CRL_FILE, X509_FILETYPE_PEM) != 1){
// PrintSSLError();
// printf ("Error reading the CRL file");
//}
// enabling verification against CRLs is not possible in prior versions
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
// set the flags of the store so that CRLs are consulted
//X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
X509_STORE_set_flags
(store,
NULL);
#endif
// create a verification context and initialize it
if (!
(verify_ctx = X509_STORE_CTX_new
()))
printf ("Error creating X509_STORE_CTX object");
// X509_STORE_CTX_init did not return an error condition in prior versions
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
if (X509_STORE_CTX_init
(verify_ctx, store, cert,
NULL) !=
1)
printf("Error initializing verification context");
#else
X509_STORE_CTX_init
(verify_ctx, store, cert,
NULL);
#endif
// verify the certificate
if (X509_verify_cert
(verify_ctx
) !=
1){
printf("Error verifying the certificate");
PrintSSLError
();
}
else{
printf ("Certificate verified correctly!\n");
}
ssl = SSL_new
(ctx
);
CHK_NULL
(ssl
);
printf("connect ...\r\n");
SSL_set_fd
(ssl, sd
);
err = SSL_connect
(ssl
);
CHK_SSL
(err
);
printf ("SSL connection using %s\n", SSL_get_cipher
(ssl
));
/* Get server's certificate (note: beware of dynamic allocation) - opt */
server_cert = SSL_get_peer_certificate
(ssl
); CHK_NULL
(server_cert
);
printf ("Server certificate:\n");
char *str = X509_NAME_oneline
(X509_get_subject_name
(server_cert
),
0,
0);
CHK_NULL
(str
);
printf ("\t subject: %s\n", str
);
OPENSSL_free
(str
);
str = X509_NAME_oneline
(X509_get_issuer_name
(server_cert
),
0,
0);
CHK_NULL
(str
);
printf ("\t issuer: %s\n", str
);
OPENSSL_free
(str
);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
X509_free
(server_cert
);
// ---------------------------------------------------
// DATA EXCHANGE - Send a message and receive a reply.
err = SSL_write
(ssl,
"GET / HTTP/1.0\r\n\r\n", strlen
("GET / HTTP/1.1\r\n\r\n")); CHK_SSL
(err
);
err = SSL_read
(ssl, buf,
sizeof(buf
) -
1); CHK_SSL
(err
);
buf
[err
] =
'\0';
printf ("Got %d chars:'%s'\n", err, buf
);
//BIO_free(sbio);
SSL_shutdown
(ssl
);
// send SSL/TLS close_notify
SSL_free
(ssl
);
SSL_CTX_free
(ctx
);
closesocket
(sd
);
cleanUp:
WSACleanup
();
return 0;
}