#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define RETURN_NULL(x) if ((x)==NULL) exit (1)
#define RETURN_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define RETURN_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(1); }
static int verify_callback(int ok, X509_STORE_CTX *ctx);
#define RSA_CLIENT_CERT "client.crt"
#define RSA_CLIENT_KEY "client.key"
#define RSA_CLIENT_CA_CERT "client_ca.crt"
#define RSA_CLIENT_CA_PATH "sys$common:[syshlp.examples.ssl]"
#define ON 1
#define OFF 0
#define MILLION 1000000
const char *url = "/URL";
void main()
{
int err;
int verify_client = OFF; /* To verify a client certificate, set ON */
int sock;
struct sockaddr_in server_addr;
char *str;
SSL_CTX *ctx;
SSL *ssl;
SSL_METHOD *meth;
X509 *server_cert;
EVP_PKEY *pkey;
BIO *sbio;
const short int s_port = 443;
const char *s_ipaddr = "127.0.0.1";
/* Load encryption & hashing algorithms for the SSL program */
SSL_library_init();
/* Load the error strings for SSL & CRYPTO APIs */
SSL_load_error_strings();
/* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */
meth = SSLv23_method();
/* Create an SSL_CTX structure */
ctx = SSL_CTX_new(meth);
RETURN_NULL(ctx);
/*----------------------------------------------------------*/
if(verify_client == ON)
{
/* Load the client certificate into the SSL_CTX structure */
if (SSL_CTX_use_certificate_file(ctx, RSA_CLIENT_CERT, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
/* Load the private-key corresponding to the client certificate */
if (SSL_CTX_use_PrivateKey_file(ctx, RSA_CLIENT_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
/* Check if the client certificate and private-key matches */
if (!SSL_CTX_check_private_key(ctx))
{
fprintf(stderr,"Private key does not match the certificate public key\n");
exit(1);
}
}
/* Load the RSA CA certificate into the SSL_CTX structure */
/* This will allow this client to verify the server's */
/* certificate. */
/* ------------------------------------------------------------- */
/* Set up a TCP socket */
sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
RETURN_ERR(sock, "socket");
memset (&server_addr, '\0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(s_port); /* Server Port number */
server_addr.sin_addr.s_addr = inet_addr(s_ipaddr); /* Server IP */
/* Establish a TCP/IP connection to the SSL client */
err = connect(sock, (struct sockaddr*) &server_addr, sizeof(server_addr));
RETURN_ERR(err, "connect");
/* ----------------------------------------------- */
/* An SSL structure is created */
ssl = SSL_new (ctx);
sbio=BIO_new_socket(sock,BIO_NOCLOSE);
SSL_set_bio(ssl,sbio,sbio);
RETURN_NULL(ssl);
/* Assign the socket into the SSL structure (SSL and socket without BIO) */
//SSL_set_fd(ssl, sock);
//printf("SSL_set_fd\n");
/* Perform SSL Handshake on the SSL client */
err = SSL_connect(ssl);
RETURN_SSL(err);
/* Informational output (optional) */
//printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get the server's certificate (optional) */
/*server_cert = SSL_get_peer_certificate (ssl);
if (server_cert != NULL)
{
printf ("Server certificate:\n");
str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
RETURN_NULL(str);
printf ("\t subject: %s\n", str);
free (str);
str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0);
RETURN_NULL(str);
printf ("\t issuer: %s\n", str);
free(str);
X509_free (server_cert);
}
else
printf("The SSL server does not have certificate.\n");
*/
/*-------- DATA EXCHANGE - send message and receive reply. -------*/
/* Send data to the SSL server */
//err=SSL_write(ssl,request,request_len);
char request[2048];
sprintf(request,"GET %s HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (Linux; X11)\r\nHost: %s\r\n\r\n",
url,s_ipaddr);
err=SSL_write(ssl,request,strlen(request));
switch(SSL_get_error(ssl,err)){
case SSL_ERROR_NONE:
//if(request_len!=err)
if(strlen(request)!=err)
printf("Incomplete write! \n");
break;
default:
printf("SSL write problem \n");
}
RETURN_SSL(err);
/* Receive data from the SSL server */
/* Now read the server's response, assuming
that it's terminated by a close */
char buf[10000];
int len = 0;
while(1)
{
err=SSL_read(ssl,buf,10000);
switch(SSL_get_error(ssl,err)){
case SSL_ERROR_NONE:
len=err;
break;
case SSL_ERROR_WANT_READ:
continue;
case SSL_ERROR_ZERO_RETURN:
goto done;
case SSL_ERROR_SYSCALL:
printf(stderr,"SSL Error: Premature close\n");
goto done;
default:
printf("SSL read problem \n");
}
//printf("%s\n",buf);
}
/*--------------- SSL closure ---------------*/
/* Shutdown the client side of the SSL connection */
done:
err = SSL_shutdown(ssl);
RETURN_SSL(err);
/* Terminate communication on a socket */
err = close(sock);
RETURN_ERR(err, "close");
/* Free the SSL structure */
SSL_free(ssl);
/* Free the SSL_CTX structure */
SSL_CTX_free(ctx);
}
|