1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-10-15 11:26:40 +03:00

* SNI added

* Some non-C sample code updated.

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@271 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2016-12-12 19:27:38 +00:00
committed by Ivan Grokhotkov
parent a68324f17c
commit 425067abe6
18 changed files with 5701 additions and 48 deletions

105
bindings/Config.in Normal file
View File

@@ -0,0 +1,105 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "Language Bindings"
config CONFIG_BINDINGS
bool "Create language bindings"
default n
help
axTLS supports language bindings in C#, VB.NET, Java and Perl.
Select Y here if you want to build the various language bindings.
config CONFIG_CSHARP_BINDINGS
bool "Create C# bindings"
default n
depends on CONFIG_BINDINGS
help
Build C# bindings.
This requires .NET to be installed on Win32 platforms and mono to be
installed on all other platforms.
config CONFIG_VBNET_BINDINGS
bool "Create VB.NET bindings"
default n
depends on CONFIG_BINDINGS
help
Build VB.NET bindings.
This requires the .NET to be installed and is only built under Win32
platforms.
menu ".Net Framework"
depends on CONFIG_CSHARP_BINDINGS || CONFIG_VBNET_BINDINGS
config CONFIG_DOT_NET_FRAMEWORK_BASE
string "Location of .NET Framework"
default "c:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727"
endmenu
config CONFIG_JAVA_BINDINGS
bool "Create Java bindings"
default n
depends on CONFIG_BINDINGS
help
Build Java bindings.
Current Issues (see README):
* Needs Java 1.4 or better.
* If building under Win32 it will use the Win32 JDK.
menu "Java Home"
depends on CONFIG_JAVA_BINDINGS
config CONFIG_JAVA_HOME
string "Location of JDK"
default "c:\\Program Files\\Java\\jdk1.5.0_06" if CONFIG_PLATFORM_WIN32 || CONFIG_PLATFORM_CYGWIN
default "/usr/lib/jvm/java-7-openjdk-amd64" if !CONFIG_PLATFORM_WIN32 && !CONFIG_PLATFORM_CYGWIN
depends on CONFIG_JAVA_BINDINGS
help
The location of Sun's JDK.
endmenu
config CONFIG_PERL_BINDINGS
bool "Create Perl bindings"
default n
depends on CONFIG_BINDINGS
help
Build Perl bindings.
Current Issues (see README):
* 64 bit versions don't work at present.
* libperl.so needs to be in the shared library path.
menu "Perl Home"
depends on CONFIG_PERL_BINDINGS && CONFIG_PLATFORM_WIN32
config CONFIG_PERL_CORE
string "Location of Perl CORE"
default "c:\\perl\\lib\\CORE"
help:
works with ActiveState
"http://www.activestate.com/Products/ActivePerl"
config CONFIG_PERL_LIB
string "Name of Perl Library"
default "perl58.lib"
endmenu
config CONFIG_LUA_BINDINGS
bool "Create Lua bindings"
default n
depends on CONFIG_BINDINGS && !CONFIG_PLATFORM_WIN32
help
Build Lua bindings (see www.lua.org).
menu "Lua Home"
depends on CONFIG_LUA_BINDINGS
config CONFIG_LUA_CORE
string "Location of Lua CORE"
default "/usr/local"
help:
If the Lua exists on another directory then this needs to be changed
endmenu
endmenu

491
bindings/csharp/axTLS.cs Normal file
View File

@@ -0,0 +1,491 @@
/*
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* A wrapper around the unmanaged interface to give a semi-decent C# API
*/
using System;
using System.Runtime.InteropServices;
using System.Net.Sockets;
/**
* @defgroup csharp_api C# API.
*
* Ensure that the appropriate Dispose() methods are called when finished with
* various objects - otherwise memory leaks will result.
* @{
*/
namespace axTLS
{
/**
* @class SSL
* @ingroup csharp_api
* @brief A representation of an SSL connection.
*/
public class SSL
{
public IntPtr m_ssl; /**< A pointer to the real SSL type */
/**
* @brief Store the reference to an SSL context.
* @param ip [in] A reference to an SSL object.
*/
public SSL(IntPtr ip)
{
m_ssl = ip;
}
/**
* @brief Free any used resources on this connection.
*
* A "Close Notify" message is sent on this connection (if possible).
* It is up to the application to close the socket.
*/
public void Dispose()
{
axtls.ssl_free(m_ssl);
}
/**
* @brief Return the result of a handshake.
* @return SSL_OK if the handshake is complete and ok.
* @see ssl.h for the error code list.
*/
public int HandshakeStatus()
{
return axtls.ssl_handshake_status(m_ssl);
}
/**
* @brief Return the SSL cipher id.
* @return The cipher id which is one of:
* - SSL_AES128_SHA (0x2f)
* - SSL_AES256_SHA (0x35)
* - SSL_AES128_SHA256 (0x3c)
* - SSL_AES256_SHA256 (0x3d)
*/
public byte GetCipherId()
{
return axtls.ssl_get_cipher_id(m_ssl);
}
/**
* @brief Get the session id for a handshake.
*
* This will be a 32 byte sequence and is available after the first
* handshaking messages are sent.
* @return The session id as a 32 byte sequence.
* @note A SSLv23 handshake may have only 16 valid bytes.
*/
public byte[] GetSessionId()
{
IntPtr ptr = axtls.ssl_get_session_id(m_ssl);
byte sess_id_size = axtls.ssl_get_session_id_size(m_ssl);
byte[] result = new byte[sess_id_size];
Marshal.Copy(ptr, result, 0, sess_id_size);
return result;
}
/**
* @brief Retrieve an X.509 distinguished name component.
*
* When a handshake is complete and a certificate has been exchanged,
* then the details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's
* common name matches the URL.
*
* A full handshake needs to occur for this call to work.
*
* @param component [in] one of:
* - SSL_X509_CERT_COMMON_NAME
* - SSL_X509_CERT_ORGANIZATION
* - SSL_X509_CERT_ORGANIZATIONAL_NAME
* - SSL_X509_CA_CERT_COMMON_NAME
* - SSL_X509_CA_CERT_ORGANIZATION
* - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
* @return The appropriate string (or null if not defined)
*/
public string GetCertificateDN(int component)
{
return axtls.ssl_get_cert_dn(m_ssl, component);
}
}
/**
* @class SSLUtil
* @ingroup csharp_api
* @brief Some global helper functions.
*/
public class SSLUtil
{
/**
* @brief Return the build mode of the axTLS project.
* @return The build mode is one of:
* - SSL_BUILD_SERVER_ONLY
* - SSL_BUILD_ENABLE_VERIFICATION
* - SSL_BUILD_ENABLE_CLIENT
* - SSL_BUILD_FULL_MODE
*/
public static int BuildMode()
{
return axtls.ssl_get_config(axtls.SSL_BUILD_MODE);
}
/**
* @brief Return the number of chained certificates that the
* client/server supports.
* @return The number of supported server certificates.
*/
public static int MaxCerts()
{
return axtls.ssl_get_config(axtls.SSL_MAX_CERT_CFG_OFFSET);
}
/**
* @brief Return the number of CA certificates that the client/server
* supports.
* @return The number of supported CA certificates.
*/
public static int MaxCACerts()
{
return axtls.ssl_get_config(axtls.SSL_MAX_CA_CERT_CFG_OFFSET);
}
/**
* @brief Indicate if PEM is supported.
* @return true if PEM supported.
*/
public static bool HasPEM()
{
return axtls.ssl_get_config(axtls.SSL_HAS_PEM) > 0 ? true : false;
}
/**
* @brief Display the text string of the error.
* @param error_code [in] The integer error code.
*/
public static void DisplayError(int error_code)
{
axtls.ssl_display_error(error_code);
}
/**
* @brief Return the version of the axTLS project.
*/
public static string Version()
{
return axtls.ssl_version();
}
}
/**
* @class SSLCTX
* @ingroup csharp_api
* @brief A base object for SSLServer/SSLClient.
*/
public class SSLCTX
{
/**
* @brief A reference to the real client/server context.
*/
protected IntPtr m_ctx;
/**
* @brief Establish a new client/server context.
*
* This function is called before any client/server SSL connections are
* made. If multiple threads are used, then each thread will have its
* own SSLCTX context. Any number of connections may be made with a
* single context.
*
* Each new connection will use the this context's private key and
* certificate chain. If a different certificate chain is required,
* then a different context needs to be be used.
*
* @param options [in] Any particular options. At present the options
* supported are:
* - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if
* the server authentication fails. The certificate can be
* authenticated later with a call to VerifyCert().
* - SSL_CLIENT_AUTHENTICATION (server only): Enforce client
* authentication i.e. each handshake will include a "certificate
* request" message from the server.
* - SSL_DISPLAY_BYTES (full mode build only): Display the byte
* sequences during the handshake.
* - SSL_DISPLAY_STATES (full mode build only): Display the state
* changes during the handshake.
* - SSL_DISPLAY_CERTS (full mode build only): Display the
* certificates that are passed during a handshake.
* - SSL_DISPLAY_RSA (full mode build only): Display the RSA key
* details that are passed during a handshake.
* @param num_sessions [in] The number of sessions to be used for
* session caching. If this value is 0, then there is no session
* caching.
* @return A client/server context.
*/
protected SSLCTX(uint options, int num_sessions)
{
m_ctx = axtls.ssl_ctx_new(options, num_sessions);
}
/**
* @brief Remove a client/server context.
*
* Frees any used resources used by this context. Each connection will
* be sent a "Close Notify" alert (if possible).
*/
public void Dispose()
{
axtls.ssl_ctx_free(m_ctx);
}
/**
* @brief Read the SSL data stream.
* @param ssl [in] An SSL object reference.
* @param in_data [out] After a successful read, the decrypted data
* will be here. It will be null otherwise.
* @return The number of decrypted bytes:
* - if > 0, then the handshaking is complete and we are returning the
* number of decrypted bytes.
* - SSL_OK if the handshaking stage is successful (but not yet
* complete).
* - < 0 if an error.
* @see ssl.h for the error code list.
* @note Use in_data before doing any successive ssl calls.
*/
public int Read(SSL ssl, out byte[] in_data)
{
IntPtr ptr = IntPtr.Zero;
int ret = axtls.ssl_read(ssl.m_ssl, ref ptr);
if (ret > axtls.SSL_OK)
{
in_data = new byte[ret];
Marshal.Copy(ptr, in_data, 0, ret);
}
else
{
in_data = null;
}
return ret;
}
/**
* @brief Write to the SSL data stream.
* @param ssl [in] An SSL obect reference.
* @param out_data [in] The data to be written
* @return The number of bytes sent, or if < 0 if an error.
* @see ssl.h for the error code list.
*/
public int Write(SSL ssl, byte[] out_data)
{
return axtls.ssl_write(ssl.m_ssl, out_data, out_data.Length);
}
/**
* @brief Write to the SSL data stream.
* @param ssl [in] An SSL obect reference.
* @param out_data [in] The data to be written
* @param out_len [in] The number of bytes to be written
* @return The number of bytes sent, or if < 0 if an error.
* @see ssl.h for the error code list.
*/
public int Write(SSL ssl, byte[] out_data, int out_len)
{
return axtls.ssl_write(ssl.m_ssl, out_data, out_len);
}
/**
* @brief Find an ssl object based on a Socket reference.
*
* Goes through the list of SSL objects maintained in a client/server
* context to look for a socket match.
* @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
* @return A reference to the SSL object. Returns null if the object
* could not be found.
*/
public SSL Find(Socket s)
{
int client_fd = s.Handle.ToInt32();
return new SSL(axtls. ssl_find(m_ctx, client_fd));
}
/**
* @brief Authenticate a received certificate.
*
* This call is usually made by a client after a handshake is complete
* and the context is in SSL_SERVER_VERIFY_LATER mode.
* @param ssl [in] An SSL object reference.
* @return SSL_OK if the certificate is verified.
*/
public int VerifyCert(SSL ssl)
{
return axtls.ssl_verify_cert(ssl.m_ssl);
}
/**
* @brief Force the client to perform its handshake again.
*
* For a client this involves sending another "client hello" message.
* For the server is means sending a "hello request" message.
*
* This is a blocking call on the client (until the handshake
* completes).
* @param ssl [in] An SSL object reference.
* @return SSL_OK if renegotiation instantiation was ok
*/
public int Renegotiate(SSL ssl)
{
return axtls.ssl_renegotiate(ssl.m_ssl);
}
/**
* @brief Load a file into memory that is in binary DER or ASCII PEM
* format.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param obj_type [in] The format of the file. Can be one of:
* - SSL_OBJ_X509_CERT (no password required)
* - SSL_OBJ_X509_CACERT (no password required)
* - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
* - SSL_OBJ_P8 (RC4-128 encrypted data supported)
* - SSL_OBJ_P12 (RC4-128 encrypted data supported)
*
* PEM files are automatically detected (if supported).
* @param filename [in] The location of a file in DER/PEM format.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
*/
public int ObjLoad(int obj_type, string filename, string password)
{
return axtls.ssl_obj_load(m_ctx, obj_type, filename, password);
}
/**
* @brief Transfer binary data into the object loader.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param obj_type [in] The format of the memory data.
* @param data [in] The binary data to be loaded.
* @param len [in] The amount of data to be loaded.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
*/
public int ObjLoad(int obj_type, byte[] data, int len, string password)
{
return axtls.ssl_obj_memory_load(m_ctx, obj_type,
data, len, password);
}
}
/**
* @class SSLServer
* @ingroup csharp_api
* @brief The server context.
*
* All server connections are started within a server context.
*/
public class SSLServer : SSLCTX
{
/**
* @brief Start a new server context.
*
* @see SSLCTX for details.
*/
public SSLServer(uint options, int num_sessions) :
base(options, num_sessions) {}
/**
* @brief Establish a new SSL connection to an SSL client.
*
* It is up to the application to establish the initial socket
* connection.
*
* Call Dispose() when the connection is to be removed.
* @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
* @return An SSL object reference.
*/
public SSL Connect(Socket s)
{
int client_fd = s.Handle.ToInt32();
return new SSL(axtls.ssl_server_new(m_ctx, client_fd));
}
}
/**
* @class SSLClient
* @ingroup csharp_api
* @brief The client context.
*
* All client connections are started within a client context.
*/
public class SSLClient : SSLCTX
{
/**
* @brief Start a new client context.
*
* @see SSLCTX for details.
*/
public SSLClient(uint options, int num_sessions) :
base(options, num_sessions) {}
/**
* @brief Establish a new SSL connection to an SSL server.
*
* It is up to the application to establish the initial socket
* connection.
*
* This is a blocking call - it will finish when the handshake is
* complete (or has failed).
*
* Call Dispose() when the connection is to be removed.
* @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
* @param session_id [in] A 32 byte session id for session resumption.
* This can be null if no session resumption is not required.
* @return An SSL object reference. Use SSL.handshakeStatus() to check
* if a handshake succeeded.
*/
public SSL Connect(Socket s, byte[] session_id)
{
int client_fd = s.Handle.ToInt32();
byte sess_id_size = (byte)(session_id != null ?
session_id.Length : 0);
return new SSL(axtls.ssl_client_new(m_ctx, client_fd, session_id,
sess_id_size));
}
}
}
/** @} */

View File

@@ -0,0 +1,392 @@
#!/usr/bin/perl
#
# Copyright (c) 2007, Cameron Rich
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#===============================================================
# Transforms function signature into SWIG format
sub transformSignature
{
foreach $item (@_)
{
$line =~ s/STDCALL //g;
$line =~ s/EXP_FUNC/extern/g;
# make API Java more 'byte' friendly
$line =~ s/uint32_t/int/g;
$line =~ s/const uint8_t \* /const unsigned char \* /g;
$line =~ s/\(void\)/()/g;
if ($ARGV[0] eq "-java")
{
$line =~ s/.*ssl_read.*//g;
$line =~ s/const uint8_t \*(\w+)/const signed char $1\[\]/g;
$line =~ s/uint8_t/signed char/g;
}
elsif ($ARGV[0] eq "-perl")
{
$line =~ s/const uint8_t \*(\w+)/const unsigned char $1\[\]/g;
$line =~ s/uint8_t/unsigned char/g;
}
else # lua
{
$line =~ s/const uint8_t \*session_id/const unsigned char session_id\[\]/g;
$line =~ s/const uint8_t \*\w+/unsigned char *INPUT/g;
$line =~ s/uint8_t/unsigned char/g;
}
}
return $line;
}
# Parse input file
sub parseFile
{
foreach $line (@_)
{
next if $line =~ /ssl_x509_create/; # ignore for now
# test for a #define
if (!$skip && $line =~ m/^#define/)
{
$splitDefine = 1 if $line =~ m/\\$/;
print DATA_OUT $line;
# check line is not split
next if $splitDefine == 1;
}
# pick up second line of #define statement
if ($splitDefine)
{
print DATA_OUT $line;
# check line is not split
$splitDefine = ($line =~ m/\\$/);
next;
}
# test for function declaration
if (!$skip && $line =~ /EXP_FUNC/ && $line !~/\/\*/)
{
$line = transformSignature($line);
$splitFunctionDeclaration = $line !~ /;/;
print DATA_OUT $line;
next;
}
if ($splitFunctionDeclaration)
{
$line = transformSignature($line);
$splitFunctionDeclaration = $line !~ /;/;
print DATA_OUT $line;
next;
}
}
}
#===============================================================
# Determine which module to build from cammand-line options
use strict;
use Getopt::Std;
my $module;
my $interfaceFile;
my $data_file;
my $skip;
my $splitLine;
my @raw_data;
if (not defined $ARGV[0])
{
die "Usage: $0 [-java | -perl | -lua]\n";
}
if ($ARGV[0] eq "-java")
{
print "Generating Java interface file\n";
$module = "axtlsj";
$interfaceFile = "java/axTLSj.i";
}
elsif ($ARGV[0] eq "-perl")
{
print "Generating Perl interface file\n";
$module = "axtlsp";
$interfaceFile = "perl/axTLSp.i";
}
elsif ($ARGV[0] eq "-lua")
{
print "Generating lua interface file\n";
$module = "axtlsl";
$interfaceFile = "lua/axTLSl.i";
}
else
{
die "Usage: $0 [-java | -perl | -lua]\n";
}
# Input file required to generate SWIG interface file.
$data_file = "../ssl/ssl.h";
# Open input files
open(DATA_IN, $data_file) || die("Could not open file ($data_file)!");
@raw_data = <DATA_IN>;
# Open output file
open(DATA_OUT, ">$interfaceFile") || die("Cannot Open File");
#
# I wish I could say it was easy to generate the Perl/Java/Lua bindings,
# but each had their own set of challenges... :-(.
#
print DATA_OUT << "END";
%module $module\n
/* include our own header */
%inline %{
#include "ssl.h"
%}
%include "typemaps.i"
/* Some SWIG magic to make the API a bit more Java friendly */
#ifdef SWIGJAVA
%apply long { SSL * };
%apply long { SSL_CTX * };
%apply long { SSLObjLoader * };
/* allow "unsigned char []" to become "byte[]" */
%include "arrays_java.i"
/* convert these pointers to use long */
%apply signed char[] {unsigned char *};
%apply signed char[] {signed char *};
/* allow ssl_get_session_id() to return "byte[]" */
%typemap(out) unsigned char * ssl_get_session_id \"if (result) jresult = SWIG_JavaArrayOutSchar(jenv, result, ssl_get_session_id_size((SSL const *)arg1));\"
/* allow ssl_client_new() to have a null session_id input */
%typemap(in) const signed char session_id[] (jbyte *jarr) {
if (jarg3 == NULL)
{
jresult = (jint)ssl_client_new(arg1,arg2,NULL,0);
return jresult;
}
if (!SWIG_JavaArrayInSchar(jenv, &jarr, &arg3, jarg3)) return 0;
}
/* Lot's of work required for an ssl_read() due to its various custom
* requirements.
*/
%native (ssl_read) int ssl_read(SSL *ssl, jobject in_data);
%{
JNIEXPORT jint JNICALL Java_axTLSj_axtlsjJNI_ssl_1read(JNIEnv *jenv, jclass jcls, jint jarg1, jobject jarg2) {
jint jresult = 0 ;
SSL *arg1;
unsigned char *arg2;
jbyte *jarr;
int result;
JNIEnv e = *jenv;
jclass holder_class;
jfieldID fid;
arg1 = (SSL *)jarg1;
result = (int)ssl_read(arg1, &arg2);
/* find the "m_buf" entry in the SSLReadHolder class */
if (!(holder_class = e->GetObjectClass(jenv,jarg2)) ||
!(fid = e->GetFieldID(jenv,holder_class, "m_buf", "[B")))
return SSL_NOT_OK;
if (result > SSL_OK)
{
int i;
/* create a new byte array to hold the read data */
jbyteArray jarray = e->NewByteArray(jenv, result);
/* copy the bytes across to the java byte array */
jarr = e->GetByteArrayElements(jenv, jarray, 0);
for (i = 0; i < result; i++)
jarr[i] = (jbyte)arg2[i];
/* clean up and set the new m_buf object */
e->ReleaseByteArrayElements(jenv, jarray, jarr, 0);
e->SetObjectField(jenv, jarg2, fid, jarray);
}
else /* set to null */
e->SetObjectField(jenv, jarg2, fid, NULL);
jresult = (jint)result;
return jresult;
}
%}
/* Big hack to get hold of a socket's file descriptor */
%typemap (jtype) long "Object"
%typemap (jstype) long "Object"
%native (getFd) int getFd(long sock);
%{
JNIEXPORT jint JNICALL Java_axTLSj_axtlsjJNI_getFd(JNIEnv *env, jclass jcls, jobject sock)
{
JNIEnv e = *env;
jfieldID fid;
jobject impl;
jobject fdesc;
/* get the SocketImpl from the Socket */
if (!(jcls = e->GetObjectClass(env,sock)) ||
!(fid = e->GetFieldID(env,jcls,"impl","Ljava/net/SocketImpl;")) ||
!(impl = e->GetObjectField(env,sock,fid))) return -1;
/* get the FileDescriptor from the SocketImpl */
if (!(jcls = e->GetObjectClass(env,impl)) ||
!(fid = e->GetFieldID(env,jcls,"fd","Ljava/io/FileDescriptor;")) ||
!(fdesc = e->GetObjectField(env,impl,fid))) return -1;
/* get the fd from the FileDescriptor */
if (!(jcls = e->GetObjectClass(env,fdesc)) ||
!(fid = e->GetFieldID(env,jcls,"fd","I"))) return -1;
/* return the descriptor */
return e->GetIntField(env,fdesc,fid);
}
%}
#endif
/* Some SWIG magic to make the API a bit more Perl friendly */
#ifdef SWIGPERL
/* for ssl_session_id() */
%typemap(out) const unsigned char * {
SV *svs = newSVpv((unsigned char *)\$1, ssl_get_session_id_size((SSL const *)arg1));
\$result = newRV(svs);
sv_2mortal(\$result);
argvi++;
}
/* for ssl_write() */
%typemap(in) const unsigned char out_data[] {
SV* tempsv;
if (!SvROK(\$input))
croak("Argument \$argnum is not a reference.");
tempsv = SvRV(\$input);
if (SvTYPE(tempsv) != SVt_PV)
croak("Argument \$argnum is not an string.");
\$1 = (unsigned char *)SvPV(tempsv, PL_na);
}
/* for ssl_read() */
%typemap(in) unsigned char **in_data (unsigned char *buf) {
\$1 = &buf;
}
%typemap(argout) unsigned char **in_data {
if (result > SSL_OK) {
SV *svs = newSVpv(*\$1, result);
\$result = newRV(svs);
sv_2mortal(\$result);
argvi++;
}
}
/* for ssl_client_new() */
%typemap(in) const unsigned char session_id[] {
/* check for a reference */
if (SvOK(\$input) && SvROK(\$input)) {
SV* tempsv = SvRV(\$input);
if (SvTYPE(tempsv) != SVt_PV)
croak("Argument \$argnum is not an string.");
\$1 = (unsigned char *)SvPV(tempsv, PL_na);
}
else
\$1 = NULL;
}
#endif
/* Some SWIG magic to make the API a bit more Lua friendly */
#ifdef SWIGLUA
SWIG_NUMBER_TYPEMAP(unsigned char);
SWIG_TYPEMAP_NUM_ARR(uchar,unsigned char);
/* for ssl_session_id() */
%typemap(out) const unsigned char * {
int i;
lua_newtable(L);
for (i = 0; i < ssl_get_session_id_size((SSL const *)arg1); i++){
lua_pushnumber(L,(lua_Number)result[i]);
lua_rawseti(L,-2,i+1); /* -1 is the number, -2 is the table */
}
SWIG_arg++;
}
/* for ssl_read() */
%typemap(in) unsigned char **in_data (unsigned char *buf) {
\$1 = &buf;
}
%typemap(argout) unsigned char **in_data {
if (result > SSL_OK) {
int i;
lua_newtable(L);
for (i = 0; i < result; i++){
lua_pushnumber(L,(lua_Number)buf2[i]);
lua_rawseti(L,-2,i+1); /* -1 is the number, -2 is the table */
}
SWIG_arg++;
}
}
/* for ssl_client_new() */
%typemap(in) const unsigned char session_id[] {
if (lua_isnil(L,\$input))
\$1 = NULL;
else
\$1 = SWIG_get_uchar_num_array_fixed(L,\$input, ssl_get_session_id((SSL const *)\$1));
}
#endif
END
# Initialise loop variables
$skip = 1;
$splitLine = 0;
parseFile(@raw_data);
close(DATA_IN);
close(DATA_OUT);
#===============================================================

137
bindings/java/SSL.java Normal file
View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
import java.io.*;
import java.util.*;
/**
* @defgroup java_api Java API.
*
* Ensure that the appropriate dispose() methods are called when finished with
* various objects - otherwise memory leaks will result.
*/
/**
* @class SSL
* @ingroup java_api
* @brief A representation of an SSL connection.
*
*/
public class SSL
{
public int m_ssl; /**< A pointer to the real SSL type */
/**
* @brief Store the reference to an SSL context.
* @param ip [in] A reference to an SSL object.
*/
public SSL(int ip)
{
m_ssl = ip;
}
/**
* @brief Free any used resources on this connection.
*
* A "Close Notify" message is sent on this connection (if possible). It
* is up to the application to close the socket.
*/
public void dispose()
{
axtlsj.ssl_free(m_ssl);
}
/**
* @brief Return the result of a handshake.
* @return SSL_OK if the handshake is complete and ok.
* @see ssl.h for the error code list.
*/
public int handshakeStatus()
{
return axtlsj.ssl_handshake_status(m_ssl);
}
/**
* @brief Return the SSL cipher id.
* @return The cipher id which is one of:
* - SSL_AES128_SHA (0x2f)
* - SSL_AES256_SHA (0x35)
* - SSL_AES128_SHA256 (0x3c)
* - SSL_AES256_SHA256 (0x3d)
*/
public byte getCipherId()
{
return axtlsj.ssl_get_cipher_id(m_ssl);
}
/**
* @brief Get the session id for a handshake.
*
* This will be a 32 byte sequence and is available after the first
* handshaking messages are sent.
* @return The session id as a 32 byte sequence.
* @note A SSLv23 handshake may have only 16 valid bytes.
*/
public byte[] getSessionId()
{
return axtlsj.ssl_get_session_id(m_ssl);
}
/**
* @brief Retrieve an X.509 distinguished name component.
*
* When a handshake is complete and a certificate has been exchanged,
* then the details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's common
* name matches the URL.
*
* A full handshake needs to occur for this call to work.
*
* @param component [in] one of:
* - SSL_X509_CERT_COMMON_NAME
* - SSL_X509_CERT_ORGANIZATION
* - SSL_X509_CERT_ORGANIZATIONAL_NAME
* - SSL_X509_CA_CERT_COMMON_NAME
* - SSL_X509_CA_CERT_ORGANIZATION
* - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
* @return The appropriate string (or null if not defined)
*/
public String getCertificateDN(int component)
{
return axtlsj.ssl_get_cert_dn(m_ssl, component);
}
}

134
config/makefile.conf Normal file
View File

@@ -0,0 +1,134 @@
#
# Copyright (c) 2007-2016, Cameron Rich
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# A standard makefile for all makefiles
#
# All executables and libraries go here
STAGE=./_stage
ifneq ($(MAKECMDGOALS), clean)
# Give an initial rule
all:
# Win32
ifdef CONFIG_PLATFORM_WIN32
ifdef CONFIG_VISUAL_STUDIO_7_0
CONFIG_VISUAL_STUDIO_7_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_7_0_BASE))
export INCLUDE=$(shell echo "$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\include;$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\platformsdk\include")
export LIB=$(shell echo "$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\\platformsdk\lib;$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\lib")
PATH:=$(CONFIG_VISUAL_STUDIO_7_0_BASE_UNIX)/vc7/bin:$(CONFIG_VISUAL_STUDIO_7_0_BASE_UNIX)/common7/ide:$(PATH)
endif
ifdef CONFIG_VISUAL_STUDIO_8_0
CONFIG_VISUAL_STUDIO_8_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_8_0_BASE))
export INCLUDE=$(shell echo "$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\include;$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\platformsdk\include")
export LIB=$(shell echo "$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\platformsdk\lib;$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\lib")
PATH:=$(CONFIG_VISUAL_STUDIO_8_0_BASE_UNIX)/vc/bin:$(CONFIG_VISUAL_STUDIO_8_0_BASE_UNIX)/common7/ide:$(PATH)
endif
ifdef CONFIG_VISUAL_STUDIO_10_0
CONFIG_VISUAL_STUDIO_10_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_10_0_BASE))
export INCLUDE=$(shell echo "$(CONFIG_VISUAL_STUDIO_10_0_BASE)\vc\include;$(CONFIG_VISUAL_STUDIO_10_0_BASE)\..\Microsoft SDKs\Windows\v7.0A\include")
export LIB=$(shell echo "$(CONFIG_VISUAL_STUDIO_10_0_BASE)\vc\lib;$(CONFIG_VISUAL_STUDIO_10_0_BASE)\..\Microsoft SDKs\Windows\v7.0A\lib")
PATH:=$(CONFIG_VISUAL_STUDIO_10_0_BASE_UNIX)/vc/bin:$(CONFIG_VISUAL_STUDIO_10_0_BASE_UNIX)/common7/ide:$(PATH)
stuff:
@echo $(INCLUDE)
endif
CC=cl.exe
LD=link.exe
AXTLS_INCLUDE=$(shell cygpath -w $(AXTLS_HOME))
CFLAGS+=/nologo /W3 /D"WIN32" /D"_MBCS" /D"_CONSOLE" /D"_CRT_SECURE_NO_DEPRECATE" /FD /I"$(AXTLS_INCLUDE)crypto" /I"$(AXTLS_INCLUDE)ssl" /I"$(AXTLS_INCLUDE)config" /c
LDFLAGS=/nologo /subsystem:console /machine:I386
LDSHARED = /dll
AR=lib /nologo
ifdef CONFIG_DEBUG
CFLAGS += /Gm /Zi /Od /D "_DEBUG"
LDFLAGS += /debug /incremental:yes
else
CFLAGS += /O2 /D "NDEBUG"
LDFLAGS += /incremental:no
endif
else # Not Win32
-include .depend
CFLAGS += -I$(AXTLS_HOME)/config -I$(AXTLS_HOME)/ssl -I$(AXTLS_HOME)/crypto
LD=$(CC)
STRIP=$(CROSS)strip
# Solaris
ifdef CONFIG_PLATFORM_SOLARIS
CFLAGS += -DCONFIG_PLATFORM_SOLARIS
LDFLAGS += -lsocket -lnsl -lc
LDSHARED = -G
# Linux/Cygwin
else
CFLAGS += -Wall -Wstrict-prototypes -Wshadow
LDSHARED = -shared
# Linux
ifndef CONFIG_PLATFORM_CYGWIN
ifndef CONFIG_PLATFORM_NOMMU
CFLAGS += -fPIC
# Cygwin
else
CFLAGS += -DCONFIG_PLATFORM_CYGWIN
LDFLAGS += -enable-auto-import
endif
endif
endif
ifdef CONFIG_DEBUG
CFLAGS += -g
else
LDFLAGS += -s
ifdef CONFIG_PLATFORM_SOLARIS
CFLAGS += -O
else
CFLAGS += -O3
endif
endif # CONFIG_DEBUG
endif # WIN32
CFLAGS+=$(subst ",, $(strip $(CONFIG_EXTRA_CFLAGS_OPTIONS)))
LDFLAGS+=$(subst ",, $(strip $(CONFIG_EXTRA_LDFLAGS_OPTIONS)))
endif # not 'clean'
clean::
-@rm -f *.o *.obj core* *.out *~ \.depend vc*0*

912
samples/c/axssl.c Normal file
View File

@@ -0,0 +1,912 @@
/*
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Demonstrate the use of the axTLS library in C with a set of
* command-line parameters similar to openssl. In fact, openssl clients
* should be able to communicate with axTLS servers and visa-versa.
*
* This code has various bits enabled depending on the configuration. To enable
* the most interesting version, compile with the 'full mode' enabled.
*
* To see what options you have, run the following:
* > axssl s_server -?
* > axssl s_client -?
*
* The axtls shared library must be in the same directory or be found
* by the OS.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "os_port.h"
#include "ssl.h"
/* define standard input */
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
static void do_server(int argc, char *argv[]);
static void print_options(char *option);
static void print_server_options(char *option);
static void do_client(int argc, char *argv[]);
static void print_client_options(char *option);
static void display_cipher(SSL *ssl);
static void display_session_id(SSL *ssl);
/**
* Main entry point. Doesn't do much except works out whether we are a client
* or a server.
*/
int main(int argc, char *argv[])
{
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);
#elif !defined(CONFIG_PLATFORM_SOLARIS)
signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */
#endif
if (argc == 2 && strcmp(argv[1], "version") == 0)
{
printf("axssl %s %s\n", ssl_version(), __DATE__);
exit(0);
}
if (argc < 2 || (
strcmp(argv[1], "s_server") && strcmp(argv[1], "s_client")))
print_options(argc > 1 ? argv[1] : "");
strcmp(argv[1], "s_server") ?
do_client(argc, argv) : do_server(argc, argv);
return 0;
}
/**
* Implement the SSL server logic.
*/
static void do_server(int argc, char *argv[])
{
int i = 2;
uint16_t port = 4433;
uint32_t options = SSL_DISPLAY_CERTS;
int client_fd;
SSL_CTX *ssl_ctx;
int server_fd, res = 0;
socklen_t client_len;
#ifndef CONFIG_SSL_SKELETON_MODE
char *private_key_file = NULL;
const char *password = NULL;
char **cert;
int cert_index = 0;
int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
#endif
#ifdef WIN32
char yes = 1;
#else
int yes = 1;
#endif
struct sockaddr_in serv_addr;
struct sockaddr_in client_addr;
int quiet = 0;
#ifdef CONFIG_SSL_CERT_VERIFICATION
int ca_cert_index = 0;
int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
char **ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
#endif
fd_set read_set;
#ifndef CONFIG_SSL_SKELETON_MODE
cert = (char **)calloc(1, sizeof(char *)*cert_size);
#endif
while (i < argc)
{
if (strcmp(argv[i], "-accept") == 0)
{
if (i >= argc-1)
{
print_server_options(argv[i]);
}
port = atoi(argv[++i]);
}
#ifndef CONFIG_SSL_SKELETON_MODE
else if (strcmp(argv[i], "-cert") == 0)
{
if (i >= argc-1 || cert_index >= cert_size)
{
print_server_options(argv[i]);
}
cert[cert_index++] = argv[++i];
}
else if (strcmp(argv[i], "-key") == 0)
{
if (i >= argc-1)
{
print_server_options(argv[i]);
}
private_key_file = argv[++i];
options |= SSL_NO_DEFAULT_KEY;
}
else if (strcmp(argv[i], "-pass") == 0)
{
if (i >= argc-1)
{
print_server_options(argv[i]);
}
password = argv[++i];
}
#endif
else if (strcmp(argv[i], "-quiet") == 0)
{
quiet = 1;
options &= ~SSL_DISPLAY_CERTS;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
else if (strcmp(argv[i], "-verify") == 0)
{
options |= SSL_CLIENT_AUTHENTICATION;
}
else if (strcmp(argv[i], "-CAfile") == 0)
{
if (i >= argc-1 || ca_cert_index >= ca_cert_size)
{
print_server_options(argv[i]);
}
ca_cert[ca_cert_index++] = argv[++i];
}
#endif
#ifdef CONFIG_SSL_FULL_MODE
else if (strcmp(argv[i], "-debug") == 0)
{
options |= SSL_DISPLAY_BYTES;
}
else if (strcmp(argv[i], "-state") == 0)
{
options |= SSL_DISPLAY_STATES;
}
else if (strcmp(argv[i], "-show-rsa") == 0)
{
options |= SSL_DISPLAY_RSA;
}
#endif
else /* don't know what this is */
{
print_server_options(argv[i]);
}
i++;
}
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL)
{
fprintf(stderr, "Error: Server context is invalid\n");
exit(1);
}
#ifndef CONFIG_SSL_SKELETON_MODE
if (private_key_file)
{
int obj_type = SSL_OBJ_RSA_KEY;
/* auto-detect the key type from the file extension */
if (strstr(private_key_file, ".p8"))
obj_type = SSL_OBJ_PKCS8;
else if (strstr(private_key_file, ".p12"))
obj_type = SSL_OBJ_PKCS12;
if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
{
fprintf(stderr, "Error: Private key '%s' is undefined.\n",
private_key_file);
exit(1);
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL))
{
printf("Certificate '%s' is undefined.\n", cert[i]);
exit(1);
}
}
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL))
{
printf("Certificate '%s' is undefined.\n", ca_cert[i]);
exit(1);
}
}
free(ca_cert);
#endif
#ifndef CONFIG_SSL_SKELETON_MODE
free(cert);
#endif
/* Create socket for incoming connections */
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return;
}
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
/* Construct local address structure */
memset(&serv_addr, 0, sizeof(serv_addr)); /* Zero out structure */
serv_addr.sin_family = AF_INET; /* Internet address family */
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
serv_addr.sin_port = htons(port); /* Local port */
/* Bind to the local address */
if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("bind");
exit(1);
}
if (listen(server_fd, 5) < 0)
{
perror("listen");
exit(1);
}
client_len = sizeof(client_addr);
/*************************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
*************************************************************************/
for (;;)
{
SSL *ssl;
int reconnected = 0;
if (!quiet)
{
printf("ACCEPT\n");
TTY_FLUSH();
}
if ((client_fd = accept(server_fd,
(struct sockaddr *)&client_addr, &client_len)) < 0)
{
break;
}
ssl = ssl_server_new(ssl_ctx, client_fd);
/* now read (and display) whatever the client sends us */
for (;;)
{
/* allow parallel reading of client and standard input */
FD_ZERO(&read_set);
FD_SET(client_fd, &read_set);
#ifndef WIN32
/* win32 doesn't like mixing up stdin and sockets */
if (isatty(STDIN_FILENO))/* but only if we are in an active shell */
{
FD_SET(STDIN_FILENO, &read_set);
}
if ((res = select(client_fd+1, &read_set, NULL, NULL, NULL)) > 0)
{
uint8_t buf[1024];
/* read standard input? */
if (FD_ISSET(STDIN_FILENO, &read_set))
{
if (fgets((char *)buf, sizeof(buf), stdin) == NULL)
{
res = SSL_ERROR_CONN_LOST;
}
else
{
/* small hack to check renegotiation */
if (buf[0] == 'r' && (buf[1] == '\n' || buf[1] == '\r'))
{
res = ssl_renegotiate(ssl);
}
else /* write our ramblings to the client */
{
res = ssl_write(ssl, buf, strlen((char *)buf)+1);
}
}
}
else /* a socket read */
#endif
{
/* keep reading until we get something interesting */
uint8_t *read_buf;
if ((res = ssl_read(ssl, &read_buf)) == SSL_OK)
{
/* are we in the middle of doing a handshake? */
if (ssl_handshake_status(ssl) != SSL_OK)
{
reconnected = 0;
}
else if (!reconnected)
{
/* we are connected/reconnected */
if (!quiet)
{
display_session_id(ssl);
display_cipher(ssl);
}
reconnected = 1;
}
}
if (res > SSL_OK) /* display our interesting output */
{
int written = 0;
while (written < res)
{
written += write(STDOUT_FILENO, read_buf+written,
res-written);
}
TTY_FLUSH();
}
else if (res == SSL_CLOSE_NOTIFY)
{
printf("shutting down SSL\n");
TTY_FLUSH();
}
else if (res < SSL_OK && !quiet)
{
ssl_display_error(res);
}
}
#ifndef WIN32
}
#endif
if (res < SSL_OK)
{
if (!quiet)
{
printf("CONNECTION CLOSED\n");
TTY_FLUSH();
}
break;
}
}
/* client was disconnected or the handshake failed. */
ssl_free(ssl);
SOCKET_CLOSE(client_fd);
}
ssl_ctx_free(ssl_ctx);
}
/**
* Implement the SSL client logic.
*/
static void do_client(int argc, char *argv[])
{
#ifdef CONFIG_SSL_ENABLE_CLIENT
int res, i = 2;
uint16_t port = 4433;
uint32_t options = SSL_SERVER_VERIFY_LATER|SSL_DISPLAY_CERTS;
int client_fd;
char *private_key_file = NULL;
struct sockaddr_in client_addr;
struct hostent *hostent;
int reconnect = 0;
uint32_t sin_addr;
SSL_CTX *ssl_ctx;
SSL *ssl = NULL;
int quiet = 0;
int cert_index = 0, ca_cert_index = 0;
int cert_size, ca_cert_size;
char **ca_cert, **cert;
uint8_t session_id[SSL_SESSION_ID_SIZE];
fd_set read_set;
const char *password = NULL;
SSL_EXTENSIONS *extensions = NULL;
FD_ZERO(&read_set);
sin_addr = inet_addr("127.0.0.1");
cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
cert = (char **)calloc(1, sizeof(char *)*cert_size);
while (i < argc)
{
if (strcmp(argv[i], "-connect") == 0)
{
char *host, *ptr;
if (i >= argc-1)
{
print_client_options(argv[i]);
}
host = argv[++i];
if ((ptr = strchr(host, ':')) == NULL)
{
print_client_options(argv[i]);
}
*ptr++ = 0;
port = atoi(ptr);
hostent = gethostbyname(host);
if (hostent == NULL)
{
print_client_options(argv[i]);
}
sin_addr = *((uint32_t **)hostent->h_addr_list)[0];
}
else if (strcmp(argv[i], "-cert") == 0)
{
if (i >= argc-1 || cert_index >= cert_size)
{
print_client_options(argv[i]);
}
cert[cert_index++] = argv[++i];
}
else if (strcmp(argv[i], "-key") == 0)
{
if (i >= argc-1)
{
print_client_options(argv[i]);
}
private_key_file = argv[++i];
options |= SSL_NO_DEFAULT_KEY;
}
else if (strcmp(argv[i], "-CAfile") == 0)
{
if (i >= argc-1 || ca_cert_index >= ca_cert_size)
{
print_client_options(argv[i]);
}
ca_cert[ca_cert_index++] = argv[++i];
}
else if (strcmp(argv[i], "-verify") == 0)
{
options &= ~SSL_SERVER_VERIFY_LATER;
}
else if (strcmp(argv[i], "-reconnect") == 0)
{
reconnect = 4;
}
else if (strcmp(argv[i], "-quiet") == 0)
{
quiet = 1;
options &= ~SSL_DISPLAY_CERTS;
}
else if (strcmp(argv[i], "-pass") == 0)
{
if (i >= argc-1)
{
print_client_options(argv[i]);
}
password = argv[++i];
}
else if (strcmp(argv[i], "-servername") == 0)
{
if (i >= argc-1)
{
print_client_options(argv[i]);
}
extensions = ssl_ext_new();
extensions->host_name = argv[++i];
}
#ifdef CONFIG_SSL_FULL_MODE
else if (strcmp(argv[i], "-debug") == 0)
{
options |= SSL_DISPLAY_BYTES;
}
else if (strcmp(argv[i], "-state") == 0)
{
options |= SSL_DISPLAY_STATES;
}
else if (strcmp(argv[i], "-show-rsa") == 0)
{
options |= SSL_DISPLAY_RSA;
}
#endif
else /* don't know what this is */
{
print_client_options(argv[i]);
}
i++;
}
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL)
{
fprintf(stderr, "Error: Client context is invalid\n");
exit(1);
}
if (private_key_file)
{
int obj_type = SSL_OBJ_RSA_KEY;
/* auto-detect the key type from the file extension */
if (strstr(private_key_file, ".p8"))
obj_type = SSL_OBJ_PKCS8;
else if (strstr(private_key_file, ".p12"))
obj_type = SSL_OBJ_PKCS12;
if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
{
fprintf(stderr, "Error: Private key '%s' is undefined.\n",
private_key_file);
exit(1);
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL))
{
printf("Certificate '%s' is undefined.\n", cert[i]);
exit(1);
}
}
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL))
{
printf("Certificate '%s' is undefined.\n", ca_cert[i]);
exit(1);
}
}
free(cert);
free(ca_cert);
/*************************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
*************************************************************************/
client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(port);
client_addr.sin_addr.s_addr = sin_addr;
if (connect(client_fd, (struct sockaddr *)&client_addr,
sizeof(client_addr)) < 0)
{
perror("connect");
exit(1);
}
if (!quiet)
{
printf("CONNECTED\n");
TTY_FLUSH();
}
/* Try session resumption? */
if (reconnect)
{
while (reconnect--)
{
ssl = ssl_client_new(ssl_ctx, client_fd, session_id,
sizeof(session_id), extensions);
if ((res = ssl_handshake_status(ssl)) != SSL_OK)
{
if (!quiet)
{
ssl_display_error(res);
}
ssl_free(ssl);
ssl_ext_free(extensions);
exit(1);
}
display_session_id(ssl);
memcpy(session_id, ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);
if (reconnect)
{
ssl_free(ssl);
ssl_ext_free(extensions);
SOCKET_CLOSE(client_fd);
client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(client_fd, (struct sockaddr *)&client_addr,
sizeof(client_addr));
}
}
}
else
{
ssl = ssl_client_new(ssl_ctx, client_fd, NULL, 0, extensions);
}
/* check the return status */
if ((res = ssl_handshake_status(ssl)) != SSL_OK)
{
if (!quiet)
{
ssl_display_error(res);
}
exit(1);
}
if (!quiet)
{
const char *common_name = ssl_get_cert_dn(ssl,
SSL_X509_CERT_COMMON_NAME);
if (common_name)
{
printf("Common Name:\t\t\t%s\n", common_name);
}
display_session_id(ssl);
display_cipher(ssl);
}
for (;;)
{
uint8_t buf[1024];
/* allow parallel reading of server and standard input */
FD_SET(client_fd, &read_set);
#ifndef WIN32
/* win32 doesn't like mixing up stdin and sockets */
FD_SET(STDIN_FILENO, &read_set);
if ((res = select(client_fd+1, &read_set, NULL, NULL, NULL)) > 0)
{
/* read standard input? */
if (FD_ISSET(STDIN_FILENO, &read_set))
#endif
{
if (fgets((char *)buf, sizeof(buf), stdin) == NULL)
{
/* bomb out of here */
ssl_free(ssl);
break;
}
else
{
/* small hack to check renegotiation */
if (buf[0] == 'R' && (buf[1] == '\n' || buf[1] == '\r'))
{
res = ssl_renegotiate(ssl);
}
else
{
res = ssl_write(ssl, buf, strlen((char *)buf));
}
}
}
#ifndef WIN32
else /* a socket read */
{
uint8_t *read_buf;
res = ssl_read(ssl, &read_buf);
if (res > 0) /* display our interesting output */
{
int written = 0;
while (written < res)
{
written += write(STDOUT_FILENO, read_buf+written,
res-written);
}
TTY_FLUSH();
}
}
}
#endif
if (res < 0)
{
if (!quiet)
{
ssl_display_error(res);
}
break; /* get outta here */
}
}
ssl_ctx_free(ssl_ctx);
ssl_ext_free(extensions);
SOCKET_CLOSE(client_fd);
#else
print_client_options(argv[1]);
#endif
}
/**
* We've had some sort of command-line error. Print out the basic options.
*/
static void print_options(char *option)
{
printf("axssl: Error: '%s' is an invalid command.\n", option);
printf("usage: axssl [s_server|s_client|version] [args ...]\n");
exit(1);
}
/**
* We've had some sort of command-line error. Print out the server options.
*/
static void print_server_options(char *option)
{
#ifndef CONFIG_SSL_SKELETON_MODE
int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
#endif
printf("unknown option %s\n", option);
printf("usage: s_server [args ...]\n");
printf(" -accept arg\t- port to accept on (default is 4433)\n");
#ifndef CONFIG_SSL_SKELETON_MODE
printf(" -cert arg\t- certificate file to add (in addition to default)"
" to chain -\n"
"\t\t Can repeat up to %d times\n", cert_size);
printf(" -key arg\t- Private key file to use\n");
printf(" -pass\t\t- private key file pass phrase source\n");
#endif
printf(" -quiet\t\t- No server output\n");
#ifdef CONFIG_SSL_CERT_VERIFICATION
printf(" -verify\t- turn on peer certificate verification\n");
printf(" -CAfile arg\t- Certificate authority\n");
printf("\t\t Can repeat up to %d times\n", ca_cert_size);
#endif
#ifdef CONFIG_SSL_FULL_MODE
printf(" -debug\t\t- Print more output\n");
printf(" -state\t\t- Show state messages\n");
printf(" -show-rsa\t- Show RSA state\n");
#endif
exit(1);
}
/**
* We've had some sort of command-line error. Print out the client options.
*/
static void print_client_options(char *option)
{
#ifdef CONFIG_SSL_ENABLE_CLIENT
int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
#endif
printf("unknown option %s\n", option);
#ifdef CONFIG_SSL_ENABLE_CLIENT
printf("usage: s_client [args ...]\n");
printf(" -connect host:port - who to connect to (default "
"is localhost:4433)\n");
printf(" -verify\t- turn on peer certificate verification\n");
printf(" -cert arg\t- certificate file to use\n");
printf("\t\t Can repeat up to %d times\n", cert_size);
printf(" -key arg\t- Private key file to use\n");
printf(" -CAfile arg\t- Certificate authority\n");
printf("\t\t Can repeat up to %d times\n", ca_cert_size);
printf(" -quiet\t\t- No client output\n");
printf(" -reconnect\t- Drop and re-make the connection "
"with the same Session-ID\n");
printf(" -pass\t\t- Private key file pass phrase source\n");
printf(" -servername\t- Set TLS extension servername in ClientHello\n");
#ifdef CONFIG_SSL_FULL_MODE
printf(" -debug\t\t- Print more output\n");
printf(" -state\t\t- Show state messages\n");
printf(" -show-rsa\t- Show RSA state\n");
#endif
#else
printf("Change configuration to allow this feature\n");
#endif
exit(1);
}
/**
* Display what cipher we are using
*/
static void display_cipher(SSL *ssl)
{
printf("CIPHER is ");
switch (ssl_get_cipher_id(ssl))
{
case SSL_AES128_SHA:
printf("AES128-SHA");
break;
case SSL_AES256_SHA:
printf("AES256-SHA");
break;
case SSL_AES128_SHA256:
printf("AES128-SHA256");
break;
case SSL_AES256_SHA256:
printf("AES256-SHA256");
break;
default:
printf("Unknown - %d", ssl_get_cipher_id(ssl));
break;
}
printf("\n");
TTY_FLUSH();
}
/**
* Display what session id we have.
*/
static void display_session_id(SSL *ssl)
{
int i;
const uint8_t *session_id = ssl_get_session_id(ssl);
int sess_id_size = ssl_get_session_id_size(ssl);
if (sess_id_size > 0)
{
printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
for (i = 0; i < sess_id_size; i++)
{
printf("%02x", session_id[i]);
}
printf("\n-----END SSL SESSION PARAMETERS-----\n");
TTY_FLUSH();
}
}

758
samples/csharp/axssl.cs Normal file
View File

@@ -0,0 +1,758 @@
/*
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Demonstrate the use of the axTLS library in C# with a set of
* command-line parameters similar to openssl. In fact, openssl clients
* should be able to communicate with axTLS servers and visa-versa.
*
* This code has various bits enabled depending on the configuration. To enable
* the most interesting version, compile with the 'full mode' enabled.
*
* To see what options you have, run the following:
* > axssl.csharp.exe s_server -?
* > axssl.csharp.exe s_client -?
*
* The axtls shared library must be in the same directory or be found
* by the OS.
*/
using System;
using System.Net;
using System.Net.Sockets;
using axTLS;
public class axssl
{
/*
* Main()
*/
public static void Main(string[] args)
{
if (args.Length == 1 && args[0] == "version")
{
Console.WriteLine("axssl.csharp " + SSLUtil.Version());
Environment.Exit(0);
}
axssl runner = new axssl();
if (args.Length < 1 || (args[0] != "s_server" && args[0] != "s_client"))
runner.print_options(args.Length > 0 ? args[0] : "");
int build_mode = SSLUtil.BuildMode();
if (args[0] == "s_server")
runner.do_server(build_mode, args);
else
runner.do_client(build_mode, args);
}
/*
* do_server()
*/
private void do_server(int build_mode, string[] args)
{
int i = 1;
int port = 4433;
uint options = axtls.SSL_DISPLAY_CERTS;
bool quiet = false;
string password = null;
string private_key_file = null;
/* organise the cert/ca_cert lists */
int cert_size = SSLUtil.MaxCerts();
int ca_cert_size = SSLUtil.MaxCACerts();
string[] cert = new string[cert_size];
string[] ca_cert = new string[ca_cert_size];
int cert_index = 0;
int ca_cert_index = 0;
while (i < args.Length)
{
if (args[i] == "-accept")
{
if (i >= args.Length-1)
{
print_server_options(build_mode, args[i]);
}
port = Int32.Parse(args[++i]);
}
else if (args[i] == "-quiet")
{
quiet = true;
options &= ~(uint)axtls.SSL_DISPLAY_CERTS;
}
else if (build_mode >= axtls.SSL_BUILD_SERVER_ONLY)
{
if (args[i] == "-cert")
{
if (i >= args.Length-1 || cert_index >= cert_size)
{
print_server_options(build_mode, args[i]);
}
cert[cert_index++] = args[++i];
}
else if (args[i] == "-key")
{
if (i >= args.Length-1)
{
print_server_options(build_mode, args[i]);
}
private_key_file = args[++i];
options |= axtls.SSL_NO_DEFAULT_KEY;
}
else if (args[i] == "-pass")
{
if (i >= args.Length-1)
{
print_server_options(build_mode, args[i]);
}
password = args[++i];
}
else if (build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION)
{
if (args[i] == "-verify")
{
options |= axtls.SSL_CLIENT_AUTHENTICATION;
}
else if (args[i] == "-CAfile")
{
if (i >= args.Length-1 || ca_cert_index >= ca_cert_size)
{
print_server_options(build_mode, args[i]);
}
ca_cert[ca_cert_index++] = args[++i];
}
else if (build_mode == axtls.SSL_BUILD_FULL_MODE)
{
if (args[i] == "-debug")
{
options |= axtls.SSL_DISPLAY_BYTES;
}
else if (args[i] == "-state")
{
options |= axtls.SSL_DISPLAY_STATES;
}
else if (args[i] == "-show-rsa")
{
options |= axtls.SSL_DISPLAY_RSA;
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
i++;
}
/* Create socket for incoming connections */
IPEndPoint ep = new IPEndPoint(IPAddress.Any, port);
TcpListener server_sock = new TcpListener(ep);
server_sock.Start();
/**********************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
**********************************************************************/
SSLServer ssl_ctx = new SSLServer(
options, axtls.SSL_DEFAULT_SVR_SESS);
if (ssl_ctx == null)
{
Console.Error.WriteLine("Error: Server context is invalid");
Environment.Exit(1);
}
if (private_key_file != null)
{
int obj_type = axtls.SSL_OBJ_RSA_KEY;
if (private_key_file.EndsWith(".p8"))
obj_type = axtls.SSL_OBJ_PKCS8;
else if (private_key_file.EndsWith(".p12"))
obj_type = axtls.SSL_OBJ_PKCS12;
if (ssl_ctx.ObjLoad(obj_type,
private_key_file, password) != axtls.SSL_OK)
{
Console.Error.WriteLine("Private key '" + private_key_file +
"' is undefined.");
Environment.Exit(1);
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT,
cert[i], null) != axtls.SSL_OK)
{
Console.WriteLine("Certificate '" + cert[i] +
"' is undefined.");
Environment.Exit(1);
}
}
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT,
ca_cert[i], null) != axtls.SSL_OK)
{
Console.WriteLine("Certificate '" + cert[i] +
"' is undefined.");
Environment.Exit(1);
}
}
byte[] buf = null;
int res;
for (;;)
{
if (!quiet)
{
Console.WriteLine("ACCEPT");
}
Socket client_sock = server_sock.AcceptSocket();
SSL ssl = ssl_ctx.Connect(client_sock);
/* do the actual SSL handshake */
while ((res = ssl_ctx.Read(ssl, out buf)) == axtls.SSL_OK)
{
/* check when the connection has been established */
if (ssl.HandshakeStatus() == axtls.SSL_OK)
break;
/* could do something else here */
}
if (res == axtls.SSL_OK) /* connection established and ok */
{
if (!quiet)
{
display_session_id(ssl);
display_cipher(ssl);
}
/* now read (and display) whatever the client sends us */
for (;;)
{
/* keep reading until we get something interesting */
while ((res = ssl_ctx.Read(ssl, out buf)) == axtls.SSL_OK)
{
/* could do something else here */
}
if (res < axtls.SSL_OK)
{
if (!quiet)
{
Console.WriteLine("CONNECTION CLOSED");
}
break;
}
/* convert to string */
char[] str = new char[res];
for (i = 0; i < res; i++)
{
str[i] = (char)buf[i];
}
Console.Write(str);
}
}
else if (!quiet)
{
SSLUtil.DisplayError(res);
}
/* client was disconnected or the handshake failed. */
ssl.Dispose();
client_sock.Close();
}
/* ssl_ctx.Dispose(); */
}
/*
* do_client()
*/
private void do_client(int build_mode, string[] args)
{
if (build_mode < axtls.SSL_BUILD_ENABLE_CLIENT)
{
print_client_options(build_mode, args[1]);
}
int i = 1, res;
int port = 4433;
bool quiet = false;
string password = null;
int reconnect = 0;
string private_key_file = null;
string hostname = "127.0.0.1";
/* organise the cert/ca_cert lists */
int cert_index = 0;
int ca_cert_index = 0;
int cert_size = SSLUtil.MaxCerts();
int ca_cert_size = SSLUtil.MaxCACerts();
string[] cert = new string[cert_size];
string[] ca_cert = new string[ca_cert_size];
uint options = axtls.SSL_SERVER_VERIFY_LATER|axtls.SSL_DISPLAY_CERTS;
byte[] session_id = null;
while (i < args.Length)
{
if (args[i] == "-connect")
{
string host_port;
if (i >= args.Length-1)
{
print_client_options(build_mode, args[i]);
}
host_port = args[++i];
int index_colon;
if ((index_colon = host_port.IndexOf(':')) < 0)
print_client_options(build_mode, args[i]);
hostname = new string(host_port.ToCharArray(),
0, index_colon);
port = Int32.Parse(new String(host_port.ToCharArray(),
index_colon+1, host_port.Length-index_colon-1));
}
else if (args[i] == "-cert")
{
if (i >= args.Length-1 || cert_index >= cert_size)
{
print_client_options(build_mode, args[i]);
}
cert[cert_index++] = args[++i];
}
else if (args[i] == "-key")
{
if (i >= args.Length-1)
{
print_client_options(build_mode, args[i]);
}
private_key_file = args[++i];
options |= axtls.SSL_NO_DEFAULT_KEY;
}
else if (args[i] == "-CAfile")
{
if (i >= args.Length-1 || ca_cert_index >= ca_cert_size)
{
print_client_options(build_mode, args[i]);
}
ca_cert[ca_cert_index++] = args[++i];
}
else if (args[i] == "-verify")
{
options &= ~(uint)axtls.SSL_SERVER_VERIFY_LATER;
}
else if (args[i] == "-reconnect")
{
reconnect = 4;
}
else if (args[i] == "-quiet")
{
quiet = true;
options &= ~(uint)axtls.SSL_DISPLAY_CERTS;
}
else if (args[i] == "-pass")
{
if (i >= args.Length-1)
{
print_client_options(build_mode, args[i]);
}
password = args[++i];
}
else if (build_mode == axtls.SSL_BUILD_FULL_MODE)
{
if (args[i] == "-debug")
{
options |= axtls.SSL_DISPLAY_BYTES;
}
else if (args[i] == "-state")
{
options |= axtls.SSL_DISPLAY_STATES;
}
else if (args[i] == "-show-rsa")
{
options |= axtls.SSL_DISPLAY_RSA;
}
else
print_client_options(build_mode, args[i]);
}
else /* don't know what this is */
print_client_options(build_mode, args[i]);
i++;
}
// IPHostEntry hostInfo = Dns.Resolve(hostname);
IPHostEntry hostInfo = Dns.GetHostEntry(hostname);
IPAddress[] addresses = hostInfo.AddressList;
IPEndPoint ep = new IPEndPoint(addresses[0], port);
Socket client_sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client_sock.Connect(ep);
if (!client_sock.Connected)
{
Console.WriteLine("could not connect");
Environment.Exit(1);
}
if (!quiet)
{
Console.WriteLine("CONNECTED");
}
/**********************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
**********************************************************************/
SSLClient ssl_ctx = new SSLClient(options,
axtls.SSL_DEFAULT_CLNT_SESS);
if (ssl_ctx == null)
{
Console.Error.WriteLine("Error: Client context is invalid");
Environment.Exit(1);
}
if (private_key_file != null)
{
int obj_type = axtls.SSL_OBJ_RSA_KEY;
if (private_key_file.EndsWith(".p8"))
obj_type = axtls.SSL_OBJ_PKCS8;
else if (private_key_file.EndsWith(".p12"))
obj_type = axtls.SSL_OBJ_PKCS12;
if (ssl_ctx.ObjLoad(obj_type,
private_key_file, password) != axtls.SSL_OK)
{
Console.Error.WriteLine("Private key '" + private_key_file +
"' is undefined.");
Environment.Exit(1);
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT,
cert[i], null) != axtls.SSL_OK)
{
Console.WriteLine("Certificate '" + cert[i] +
"' is undefined.");
Environment.Exit(1);
}
}
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT,
ca_cert[i], null) != axtls.SSL_OK)
{
Console.WriteLine("Certificate '" + cert[i] +
"' is undefined.");
Environment.Exit(1);
}
}
SSL ssl = new SSL(new IntPtr(0)); /* keep compiler happy */
/* Try session resumption? */
if (reconnect > 0)
{
while (reconnect-- > 0)
{
ssl = ssl_ctx.Connect(client_sock, session_id);
if ((res = ssl.HandshakeStatus()) != axtls.SSL_OK)
{
if (!quiet)
{
SSLUtil.DisplayError(res);
}
ssl.Dispose();
Environment.Exit(1);
}
display_session_id(ssl);
session_id = ssl.GetSessionId();
if (reconnect > 0)
{
ssl.Dispose();
client_sock.Close();
/* and reconnect */
client_sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
client_sock.Connect(ep);
}
}
}
else
{
ssl = ssl_ctx.Connect(client_sock, null);
}
/* check the return status */
if ((res = ssl.HandshakeStatus()) != axtls.SSL_OK)
{
if (!quiet)
{
SSLUtil.DisplayError(res);
}
Environment.Exit(1);
}
if (!quiet)
{
string common_name =
ssl.GetCertificateDN(axtls.SSL_X509_CERT_COMMON_NAME);
if (common_name != null)
{
Console.WriteLine("Common Name:\t\t\t" + common_name);
}
display_session_id(ssl);
display_cipher(ssl);
}
for (;;)
{
string user_input = Console.ReadLine();
if (user_input == null)
break;
byte[] buf = new byte[user_input.Length+2];
buf[buf.Length-2] = (byte)'\n'; /* add the carriage return */
buf[buf.Length-1] = 0; /* null terminate */
for (i = 0; i < buf.Length-2; i++)
{
buf[i] = (byte)user_input[i];
}
if ((res = ssl_ctx.Write(ssl, buf, buf.Length)) < axtls.SSL_OK)
{
if (!quiet)
{
SSLUtil.DisplayError(res);
}
break;
}
}
ssl_ctx.Dispose();
}
/**
* We've had some sort of command-line error. Print out the basic options.
*/
private void print_options(string option)
{
Console.WriteLine("axssl: Error: '" + option +
"' is an invalid command.");
Console.WriteLine("usage: axssl.csharp [s_server|" +
"s_client|version] [args ...]");
Environment.Exit(1);
}
/**
* We've had some sort of command-line error. Print out the server options.
*/
private void print_server_options(int build_mode, string option)
{
int cert_size = SSLUtil.MaxCerts();
int ca_cert_size = SSLUtil.MaxCACerts();
Console.WriteLine("unknown option " + option);
Console.WriteLine("usage: s_server [args ...]");
Console.WriteLine(" -accept arg\t- port to accept on (default " +
"is 4433)");
Console.WriteLine(" -quiet\t\t- No server output");
if (build_mode >= axtls.SSL_BUILD_SERVER_ONLY)
{
Console.WriteLine(" -cert arg\t- certificate file to add (in " +
"addition to default) to chain -");
Console.WriteLine("\t\t Can repeat up to " + cert_size + " times");
Console.WriteLine(" -key arg\t- Private key file to use");
Console.WriteLine(" -pass\t\t- private key file pass phrase source");
}
if (build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION)
{
Console.WriteLine(" -verify\t- turn on peer certificate " +
"verification");
Console.WriteLine(" -CAfile arg\t- Certificate authority.");
Console.WriteLine("\t\t Can repeat up to " +
ca_cert_size + "times");
}
if (build_mode == axtls.SSL_BUILD_FULL_MODE)
{
Console.WriteLine(" -debug\t\t- Print more output");
Console.WriteLine(" -state\t\t- Show state messages");
Console.WriteLine(" -show-rsa\t- Show RSA state");
}
Environment.Exit(1);
}
/**
* We've had some sort of command-line error. Print out the client options.
*/
private void print_client_options(int build_mode, string option)
{
int cert_size = SSLUtil.MaxCerts();
int ca_cert_size = SSLUtil.MaxCACerts();
Console.WriteLine("unknown option " + option);
if (build_mode >= axtls.SSL_BUILD_ENABLE_CLIENT)
{
Console.WriteLine("usage: s_client [args ...]");
Console.WriteLine(" -connect host:port - who to connect to " +
"(default is localhost:4433)");
Console.WriteLine(" -verify\t- turn on peer certificate " +
"verification");
Console.WriteLine(" -cert arg\t- certificate file to use");
Console.WriteLine("\t\t Can repeat up to %d times", cert_size);
Console.WriteLine(" -key arg\t- Private key file to use");
Console.WriteLine(" -CAfile arg\t- Certificate authority.");
Console.WriteLine("\t\t Can repeat up to " + ca_cert_size +
" times");
Console.WriteLine(" -quiet\t\t- No client output");
Console.WriteLine(" -pass\t\t- private key file pass " +
"phrase source");
Console.WriteLine(" -reconnect\t- Drop and re-make the " +
"connection with the same Session-ID");
if (build_mode == axtls.SSL_BUILD_FULL_MODE)
{
Console.WriteLine(" -debug\t\t- Print more output");
Console.WriteLine(" -state\t\t- Show state messages");
Console.WriteLine(" -show-rsa\t- Show RSA state");
}
}
else
{
Console.WriteLine("Change configuration to allow this feature");
}
Environment.Exit(1);
}
/**
* Display what cipher we are using
*/
private void display_cipher(SSL ssl)
{
Console.Write("CIPHER is ");
switch (ssl.GetCipherId())
{
case axtls.SSL_AES128_SHA:
Console.WriteLine("AES128-SHA");
break;
case axtls.SSL_AES256_SHA:
Console.WriteLine("AES256-SHA");
break;
case axtls.SSL_AES128_SHA256:
Console.WriteLine("AES128-SHA256");
break;
case axtls.SSL_AES256_SHA256:
Console.WriteLine("AES128-SHA256");
break;
default:
Console.WriteLine("Unknown - " + ssl.GetCipherId());
break;
}
}
/**
* Display what session id we have.
*/
private void display_session_id(SSL ssl)
{
byte[] session_id = ssl.GetSessionId();
if (session_id.Length > 0)
{
Console.WriteLine("-----BEGIN SSL SESSION PARAMETERS-----");
foreach (byte b in session_id)
{
Console.Write("{0:x02}", b);
}
Console.WriteLine("\n-----END SSL SESSION PARAMETERS-----");
}
}
}

51
samples/java/Makefile Normal file
View File

@@ -0,0 +1,51 @@
#
# Copyright (c) 2007-2016, Cameron Rich
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
include ../../config/.config
include ../../config/makefile.conf
include ../../config/makefile.java.conf
all : sample
JAR=../../$(STAGE)/axtls.jar
CLASSES=../../bindings/java/classes
sample : $(JAR)
$(JAR) : $(CLASSES)/axssl.class $(wildcard $(CLASSES)/axTLSj/*.class)
jar mcvf manifest.mf $@ -C $(CLASSES) axTLSj -C $(CLASSES) axssl.class
JAVA_FILES=axssl.java
JAVA_CLASSES:=$(JAVA_FILES:%.java=$(CLASSES)/axTLSj/%.class)
$(CLASSES)/%.class : %.java
javac -d $(CLASSES) -classpath $(CLASSES) $^
clean::
-@rm -f $(TARGET)

760
samples/java/axssl.java Normal file
View File

@@ -0,0 +1,760 @@
/*
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Demonstrate the use of the axTLS library in Java with a set of
* command-line parameters similar to openssl. In fact, openssl clients
* should be able to communicate with axTLS servers and visa-versa. *
* This code has various bits enabled depending on the configuration. To enable
* the most interesting version, compile with the 'full mode' enabled.
*
* To see what options you have, run the following:
* > java -jar axtls.jar s_server -?
* > java -jar axtls.jar s_client -?
*
* The axtls/axtlsj shared libraries must be in the same directory or be found
* by the OS.
*/
import java.io.*;
import java.util.*;
import java.net.*;
import axTLSj.*;
public class axssl
{
/*
* Main()
*/
public static void main(String[] args)
{
if (args.length == 1 && args[0].equals("version"))
{
System.out.println("axtls.jar " + SSLUtil.version());
System.exit(0);
}
axssl runner = new axssl();
try
{
if (args.length < 1 ||
(!args[0].equals("s_server") &&
!args[0].equals("s_client")))
{
runner.print_options(args.length > 0 ? args[0] : "");
}
int build_mode = SSLUtil.buildMode();
if (args[0].equals("s_server"))
runner.do_server(build_mode, args);
else
runner.do_client(build_mode, args);
}
catch (Exception e)
{
System.out.println(e);
}
}
/*
* do_server()
*/
private void do_server(int build_mode, String[] args)
throws Exception
{
int i = 1;
int port = 4433;
int options = axtlsj.SSL_DISPLAY_CERTS;
boolean quiet = false;
String password = null;
String private_key_file = null;
/* organise the cert/ca_cert lists */
int cert_size = SSLUtil.maxCerts();
int ca_cert_size = SSLUtil.maxCACerts();
String[] cert = new String[cert_size];
String[] ca_cert = new String[ca_cert_size];
int cert_index = 0;
int ca_cert_index = 0;
while (i < args.length)
{
if (args[i].equals("-accept"))
{
if (i >= args.length-1)
{
print_server_options(build_mode, args[i]);
}
port = Integer.parseInt(args[++i]);
}
else if (args[i].equals("-quiet"))
{
quiet = true;
options &= ~(int)axtlsj.SSL_DISPLAY_CERTS;
}
else if (build_mode >= axtlsj.SSL_BUILD_SERVER_ONLY)
{
if (args[i].equals("-cert"))
{
if (i >= args.length-1 || cert_index >= cert_size)
{
print_server_options(build_mode, args[i]);
}
cert[cert_index++] = args[++i];
}
else if (args[i].equals("-key"))
{
if (i >= args.length-1)
{
print_server_options(build_mode, args[i]);
}
private_key_file = args[++i];
options |= axtlsj.SSL_NO_DEFAULT_KEY;
}
else if (args[i].equals("-pass"))
{
if (i >= args.length-1)
{
print_server_options(build_mode, args[i]);
}
password = args[++i];
}
else if (build_mode >= axtlsj.SSL_BUILD_ENABLE_VERIFICATION)
{
if (args[i].equals("-verify"))
{
options |= axtlsj.SSL_CLIENT_AUTHENTICATION;
}
else if (args[i].equals("-CAfile"))
{
if (i >= args.length-1 || ca_cert_index >= ca_cert_size)
{
print_server_options(build_mode, args[i]);
}
ca_cert[ca_cert_index++] = args[++i];
}
else if (build_mode == axtlsj.SSL_BUILD_FULL_MODE)
{
if (args[i].equals("-debug"))
{
options |= axtlsj.SSL_DISPLAY_BYTES;
}
else if (args[i].equals("-state"))
{
options |= axtlsj.SSL_DISPLAY_STATES;
}
else if (args[i].equals("-show-rsa"))
{
options |= axtlsj.SSL_DISPLAY_RSA;
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
}
else
print_server_options(build_mode, args[i]);
i++;
}
/* Create socket for incoming connections */
ServerSocket server_sock = new ServerSocket(port);
/**********************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
**********************************************************************/
SSLServer ssl_ctx = new SSLServer(options,
axtlsj.SSL_DEFAULT_SVR_SESS);
if (ssl_ctx == null)
throw new Exception("Error: Server context is invalid");
if (private_key_file != null)
{
int obj_type = axtlsj.SSL_OBJ_RSA_KEY;
if (private_key_file.endsWith(".p8"))
obj_type = axtlsj.SSL_OBJ_PKCS8;
else if (private_key_file.endsWith(".p12"))
obj_type = axtlsj.SSL_OBJ_PKCS12;
if (ssl_ctx.objLoad(obj_type,
private_key_file, password) != axtlsj.SSL_OK)
{
throw new Exception("Error: Private key '" + private_key_file +
"' is undefined.");
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_ctx.objLoad(axtlsj.SSL_OBJ_X509_CERT,
cert[i], null) != axtlsj.SSL_OK)
{
throw new Exception("Certificate '" + cert[i] +
"' is undefined.");
}
}
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_ctx.objLoad(axtlsj.SSL_OBJ_X509_CACERT,
ca_cert[i], null) != axtlsj.SSL_OK)
{
throw new Exception("Certificate '" + ca_cert[i] +
"' is undefined.");
}
}
int res;
SSLReadHolder rh = new SSLReadHolder();
for (;;)
{
if (!quiet)
{
System.out.println("ACCEPT");
}
Socket client_sock = server_sock.accept();
SSL ssl = ssl_ctx.connect(client_sock);
while ((res = ssl_ctx.read(ssl, rh)) == axtlsj.SSL_OK)
{
/* check when the connection has been established */
if (ssl.handshakeStatus() == axtlsj.SSL_OK)
break;
/* could do something else here */
}
if (res == axtlsj.SSL_OK) /* connection established and ok */
{
if (!quiet)
{
display_session_id(ssl);
display_cipher(ssl);
}
/* now read (and display) whatever the client sends us */
for (;;)
{
/* keep reading until we get something interesting */
while ((res = ssl_ctx.read(ssl, rh)) == axtlsj.SSL_OK)
{
/* could do something else here */
}
if (res < axtlsj.SSL_OK)
{
if (!quiet)
{
System.out.println("CONNECTION CLOSED");
}
break;
}
/* convert to String */
byte[] buf = rh.getData();
char[] str = new char[res];
for (i = 0; i < res; i++)
{
str[i] = (char)buf[i];
}
System.out.print(str);
}
}
else if (!quiet)
{
SSLUtil.displayError(res);
}
/* client was disconnected or the handshake failed. */
ssl.dispose();
client_sock.close();
}
/* ssl_ctx.dispose(); */
}
/*
* do_client()
*/
private void do_client(int build_mode, String[] args)
throws Exception
{
if (build_mode < axtlsj.SSL_BUILD_ENABLE_CLIENT)
print_client_options(build_mode, args[1]);
int i = 1, res;
int port = 4433;
boolean quiet = false;
String password = null;
int reconnect = 0;
String private_key_file = null;
String hostname = "127.0.0.1";
/* organise the cert/ca_cert lists */
int cert_index = 0;
int ca_cert_index = 0;
int cert_size = SSLUtil.maxCerts();
int ca_cert_size = SSLUtil.maxCACerts();
String[] cert = new String[cert_size];
String[] ca_cert = new String[ca_cert_size];
int options = axtlsj.SSL_SERVER_VERIFY_LATER|axtlsj.SSL_DISPLAY_CERTS;
byte[] session_id = null;
while (i < args.length)
{
if (args[i].equals("-connect"))
{
String host_port;
if (i >= args.length-1)
{
print_client_options(build_mode, args[i]);
}
host_port = args[++i];
int index_colon;
if ((index_colon = host_port.indexOf(':')) < 0)
print_client_options(build_mode, args[i]);
hostname = new String(host_port.toCharArray(),
0, index_colon);
port = Integer.parseInt(new String(host_port.toCharArray(),
index_colon+1, host_port.length()-index_colon-1));
}
else if (args[i].equals("-cert"))
{
if (i >= args.length-1 || cert_index >= cert_size)
{
print_client_options(build_mode, args[i]);
}
cert[cert_index++] = args[++i];
}
else if (args[i].equals("-CAfile"))
{
if (i >= args.length-1 || ca_cert_index >= ca_cert_size)
{
print_client_options(build_mode, args[i]);
}
ca_cert[ca_cert_index++] = args[++i];
}
else if (args[i].equals("-key"))
{
if (i >= args.length-1)
{
print_client_options(build_mode, args[i]);
}
private_key_file = args[++i];
options |= axtlsj.SSL_NO_DEFAULT_KEY;
}
else if (args[i].equals("-verify"))
{
options &= ~(int)axtlsj.SSL_SERVER_VERIFY_LATER;
}
else if (args[i].equals("-reconnect"))
{
reconnect = 4;
}
else if (args[i].equals("-quiet"))
{
quiet = true;
options &= ~(int)axtlsj.SSL_DISPLAY_CERTS;
}
else if (args[i].equals("-pass"))
{
if (i >= args.length-1)
{
print_server_options(build_mode, args[i]);
}
password = args[++i];
}
else if (build_mode == axtlsj.SSL_BUILD_FULL_MODE)
{
if (args[i].equals("-debug"))
{
options |= axtlsj.SSL_DISPLAY_BYTES;
}
else if (args[i].equals("-state"))
{
options |= axtlsj.SSL_DISPLAY_STATES;
}
else if (args[i].equals("-show-rsa"))
{
options |= axtlsj.SSL_DISPLAY_RSA;
}
else
print_client_options(build_mode, args[i]);
}
else /* don't know what this is */
print_client_options(build_mode, args[i]);
i++;
}
Socket client_sock = new Socket(hostname, port);
if (!client_sock.isConnected())
{
System.out.println("could not connect");
throw new Exception();
}
if (!quiet)
{
System.out.println("CONNECTED");
}
/**********************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
**********************************************************************/
SSLClient ssl_ctx = new SSLClient(options,
axtlsj.SSL_DEFAULT_CLNT_SESS);
if (ssl_ctx == null)
{
throw new Exception("Error: Client context is invalid");
}
if (private_key_file != null)
{
int obj_type = axtlsj.SSL_OBJ_RSA_KEY;
if (private_key_file.endsWith(".p8"))
obj_type = axtlsj.SSL_OBJ_PKCS8;
else if (private_key_file.endsWith(".p12"))
obj_type = axtlsj.SSL_OBJ_PKCS12;
if (ssl_ctx.objLoad(obj_type,
private_key_file, password) != axtlsj.SSL_OK)
{
throw new Exception("Error: Private key '" + private_key_file +
"' is undefined.");
}
}
for (i = 0; i < cert_index; i++)
{
if (ssl_ctx.objLoad(axtlsj.SSL_OBJ_X509_CERT,
cert[i], null) != axtlsj.SSL_OK)
{
throw new Exception("Certificate '" + cert[i] +
"' is undefined.");
}
}
for (i = 0; i < ca_cert_index; i++)
{
if (ssl_ctx.objLoad(axtlsj.SSL_OBJ_X509_CACERT,
ca_cert[i], null) != axtlsj.SSL_OK)
{
throw new Exception("Certificate '" + ca_cert[i] +
"' is undefined.");
}
}
SSL ssl = null;
/* Try session resumption? */
if (reconnect > 0)
{
while (reconnect-- > 0)
{
ssl = ssl_ctx.connect(client_sock, session_id);
if ((res = ssl.handshakeStatus()) != axtlsj.SSL_OK)
{
if (!quiet)
{
SSLUtil.displayError(res);
}
ssl.dispose();
throw new Exception();
}
display_session_id(ssl);
session_id = ssl.getSessionId();
if (reconnect > 0)
{
ssl.dispose();
client_sock.close();
/* and reconnect */
client_sock = new Socket(hostname, port);
}
}
}
else
{
ssl = ssl_ctx.connect(client_sock, null);
}
/* check the return status */
if ((res = ssl.handshakeStatus()) != axtlsj.SSL_OK)
{
if (!quiet)
{
SSLUtil.displayError(res);
}
throw new Exception();
}
if (!quiet)
{
String common_name =
ssl.getCertificateDN(axtlsj.SSL_X509_CERT_COMMON_NAME);
if (common_name != null)
{
System.out.println("Common Name:\t\t\t" + common_name);
}
display_session_id(ssl);
display_cipher(ssl);
}
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
for (;;)
{
String user_input = in.readLine();
if (user_input == null)
break;
byte[] buf = new byte[user_input.length()+2];
buf[buf.length-2] = (byte)'\n'; /* add the carriage return */
buf[buf.length-1] = 0; /* null terminate */
for (i = 0; i < buf.length-2; i++)
{
buf[i] = (byte)user_input.charAt(i);
}
if ((res = ssl_ctx.write(ssl, buf)) < axtlsj.SSL_OK)
{
if (!quiet)
{
SSLUtil.displayError(res);
}
break;
}
}
ssl_ctx.dispose();
}
/**
* We've had some sort of command-line error. Print out the basic options.
*/
private void print_options(String option)
{
System.out.println("axssl: Error: '" + option +
"' is an invalid command.");
System.out.println("usage: axtlsj.jar [s_server|s_client|version] " +
"[args ...]");
System.exit(1);
}
/**
* We've had some sort of command-line error. Print out the server options.
*/
private void print_server_options(int build_mode, String option)
{
int cert_size = SSLUtil.maxCerts();
int ca_cert_size = SSLUtil.maxCACerts();
System.out.println("unknown option " + option);
System.out.println("usage: s_server [args ...]");
System.out.println(" -accept arg\t- port to accept on (default " +
"is 4433)");
System.out.println(" -quiet\t\t- No server output");
if (build_mode >= axtlsj.SSL_BUILD_SERVER_ONLY)
{
System.out.println(" -cert arg\t- certificate file to add (in " +
"addition to default) to chain -");
System.out.println("\t\t Can repeat up to " + cert_size + " times");
System.out.println(" -key arg\t- Private key file to use");
System.out.println(" -pass\t\t- private key file pass phrase source");
}
if (build_mode >= axtlsj.SSL_BUILD_ENABLE_VERIFICATION)
{
System.out.println(" -verify\t- turn on peer certificate " +
"verification");
System.out.println(" -CAfile arg\t- Certificate authority. ");
System.out.println("\t\t Can repeat up to " +
ca_cert_size + " times");
}
if (build_mode == axtlsj.SSL_BUILD_FULL_MODE)
{
System.out.println(" -debug\t\t- Print more output");
System.out.println(" -state\t\t- Show state messages");
System.out.println(" -show-rsa\t- Show RSA state");
}
System.exit(1);
}
/**
* We've had some sort of command-line error. Print out the client options.
*/
private void print_client_options(int build_mode, String option)
{
int cert_size = SSLUtil.maxCerts();
int ca_cert_size = SSLUtil.maxCACerts();
System.out.println("unknown option " + option);
if (build_mode >= axtlsj.SSL_BUILD_ENABLE_CLIENT)
{
System.out.println("usage: s_client [args ...]");
System.out.println(" -connect host:port - who to connect to " +
"(default is localhost:4433)");
System.out.println(" -verify\t- turn on peer certificate " +
"verification");
System.out.println(" -cert arg\t- certificate file to use");
System.out.println(" -key arg\t- Private key file to use");
System.out.println("\t\t Can repeat up to " + cert_size +
" times");
System.out.println(" -CAfile arg\t- Certificate authority.");
System.out.println("\t\t Can repeat up to " + ca_cert_size +
" times");
System.out.println(" -quiet\t\t- No client output");
System.out.println(" -pass\t\t- private key file pass " +
"phrase source");
System.out.println(" -reconnect\t- Drop and re-make the " +
"connection with the same Session-ID");
if (build_mode == axtlsj.SSL_BUILD_FULL_MODE)
{
System.out.println(" -debug\t\t- Print more output");
System.out.println(" -state\t\t- Show state messages");
System.out.println(" -show-rsa\t- Show RSA state");
}
}
else
{
System.out.println("Change configuration to allow this feature");
}
System.exit(1);
}
/**
* Display what cipher we are using
*/
private void display_cipher(SSL ssl)
{
System.out.print("CIPHER is ");
byte ciph_id = ssl.getCipherId();
if (ciph_id == axtlsj.SSL_AES128_SHA)
System.out.println("AES128-SHA");
else if (ciph_id == axtlsj.SSL_AES256_SHA)
System.out.println("AES256-SHA");
else if (ciph_id == axtlsj.SSL_AES128_SHA256)
System.out.println("AES128-SHA256");
else if (ciph_id == axtlsj.SSL_AES256_SHA256)
System.out.println("AES256-SHA256");
else
System.out.println("Unknown - " + ssl.getCipherId());
}
public char toHexChar(int i)
{
if ((0 <= i) && (i <= 9 ))
return (char)('0' + i);
else
return (char)('a' + (i-10));
}
public void bytesToHex(byte[] data)
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++ )
{
buf.append(toHexChar((data[i]>>>4)&0x0F));
buf.append(toHexChar(data[i]&0x0F));
}
System.out.println(buf);
}
/**
* Display what session id we have.
*/
private void display_session_id(SSL ssl)
{
byte[] session_id = ssl.getSessionId();
if (session_id.length > 0)
{
System.out.println("-----BEGIN SSL SESSION PARAMETERS-----");
bytesToHex(session_id);
System.out.println("-----END SSL SESSION PARAMETERS-----");
}
}
}

562
samples/lua/axssl.lua Executable file
View File

@@ -0,0 +1,562 @@
#!/usr/local/bin/lua
--
-- Copyright (c) 2007-2016, Cameron Rich
--
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- * Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
-- * Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
-- * Neither the name of the axTLS project nor the names of its
-- contributors may be used to endorse or promote products derived
-- from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
--
-- Demonstrate the use of the axTLS library in Lua with a set of
-- command-line parameters similar to openssl. In fact, openssl clients
-- should be able to communicate with axTLS servers and visa-versa.
--
-- This code has various bits enabled depending on the configuration. To enable
-- the most interesting version, compile with the 'full mode' enabled.
--
-- To see what options you have, run the following:
-- > [lua] axssl s_server -?
-- > [lua] axssl s_client -?
--
-- The axtls/axtlsl shared libraries must be in the same directory or be found
-- by the OS.
--
--
require "bit"
require("axtlsl")
local socket = require("socket")
-- print version?
if #arg == 1 and arg[1] == "version" then
print("axssl.lua "..axtlsl.ssl_version())
os.exit(1)
end
--
-- We've had some sort of command-line error. Print out the basic options.
--
function print_options(option)
print("axssl: Error: '"..option.."' is an invalid command.")
print("usage: axssl [s_server|s_client|version] [args ...]")
os.exit(1)
end
--
-- We've had some sort of command-line error. Print out the server options.
--
function print_server_options(build_mode, option)
local cert_size = axtlsl.ssl_get_config(axtlsl.SSL_MAX_CERT_CFG_OFFSET)
local ca_cert_size = axtlsl.ssl_get_config(
axtlsl.SSL_MAX_CA_CERT_CFG_OFFSET)
print("unknown option "..option)
print("usage: s_server [args ...]")
print(" -accept\t- port to accept on (default is 4433)")
print(" -quiet\t\t- No server output")
if build_mode >= axtlsl.SSL_BUILD_SERVER_ONLY then
print(" -cert arg\t- certificate file to add (in addition to "..
"default) to chain -")
print("\t\t Can repeat up to "..cert_size.." times")
print(" -key arg\t- Private key file to use - default DER format")
print(" -pass\t\t- private key file pass phrase source")
end
if build_mode >= axtlsl.SSL_BUILD_ENABLE_VERIFICATION then
print(" -verify\t- turn on peer certificate verification")
print(" -CAfile arg\t- Certificate authority - default DER format")
print("\t\t Can repeat up to "..ca_cert_size.." times")
end
if build_mode == axtlsl.SSL_BUILD_FULL_MODE then
print(" -debug\t\t- Print more output")
print(" -state\t\t- Show state messages")
print(" -show-rsa\t- Show RSA state")
end
os.exit(1)
end
--
-- We've had some sort of command-line error. Print out the client options.
--
function print_client_options(build_mode, option)
local cert_size = axtlsl.ssl_get_config(axtlsl.SSL_MAX_CERT_CFG_OFFSET)
local ca_cert_size = axtlsl.ssl_get_config(
axtlsl.SSL_MAX_CA_CERT_CFG_OFFSET)
print("unknown option "..option)
if build_mode >= axtlsl.SSL_BUILD_ENABLE_CLIENT then
print("usage: s_client [args ...]")
print(" -connect host:port - who to connect to (default "..
"is localhost:4433)")
print(" -verify\t- turn on peer certificate verification")
print(" -cert arg\t- certificate file to use - default DER format")
print(" -key arg\t- Private key file to use - default DER format")
print("\t\t Can repeat up to "..cert_size.." times")
print(" -CAfile arg\t- Certificate authority - default DER format")
print("\t\t Can repeat up to "..ca_cert_size.."times")
print(" -quiet\t\t- No client output")
print(" -pass\t\t- private key file pass phrase source")
print(" -reconnect\t- Drop and re-make the connection "..
"with the same Session-ID")
if build_mode == axtlsl.SSL_BUILD_FULL_MODE then
print(" -debug\t\t- Print more output")
print(" -state\t\t- Show state messages")
print(" -show-rsa\t- Show RSA state")
end
else
print("Change configuration to allow this feature")
end
os.exit(1)
end
-- Implement the SSL server logic.
function do_server(build_mode)
local i = 2
local v
local port = 4433
local options = axtlsl.SSL_DISPLAY_CERTS
local quiet = false
local password = ""
local private_key_file = nil
local cert_size = axtlsl.ssl_get_config(axtlsl.SSL_MAX_CERT_CFG_OFFSET)
local ca_cert_size = axtlsl.
ssl_get_config(axtlsl.SSL_MAX_CA_CERT_CFG_OFFSET)
local cert = {}
local ca_cert = {}
while i <= #arg do
if arg[i] == "-accept" then
if i >= #arg then
print_server_options(build_mode, arg[i])
end
i = i + 1
port = arg[i]
elseif arg[i] == "-quiet" then
quiet = true
options = bit.band(options, bit.bnot(axtlsl.SSL_DISPLAY_CERTS))
elseif build_mode >= axtlsl.SSL_BUILD_SERVER_ONLY then
if arg[i] == "-cert" then
if i >= #arg or #cert >= cert_size then
print_server_options(build_mode, arg[i])
end
i = i + 1
table.insert(cert, arg[i])
elseif arg[i] == "-key" then
if i >= #arg then
print_server_options(build_mode, arg[i])
end
i = i + 1
private_key_file = arg[i]
options = bit.bor(options, axtlsl.SSL_NO_DEFAULT_KEY)
elseif arg[i] == "-pass" then
if i >= #arg then
print_server_options(build_mode, arg[i])
end
i = i + 1
password = arg[i]
elseif build_mode >= axtlsl.SSL_BUILD_ENABLE_VERIFICATION then
if arg[i] == "-verify" then
options = bit.bor(options, axtlsl.SSL_CLIENT_AUTHENTICATION)
elseif arg[i] == "-CAfile" then
if i >= #arg or #ca_cert >= ca_cert_size then
print_server_options(build_mode, arg[i])
end
i = i + 1
table.insert(ca_cert, arg[i])
elseif build_mode == axtlsl.SSL_BUILD_FULL_MODE then
if arg[i] == "-debug" then
options = bit.bor(options, axtlsl.SSL_DISPLAY_BYTES)
elseif arg[i] == "-state" then
options = bit.bor(options, axtlsl.SSL_DISPLAY_STATES)
elseif arg[i] == "-show-rsa" then
options = bit.bor(options, axtlsl.SSL_DISPLAY_RSA)
else
print_server_options(build_mode, arg[i])
end
else
print_server_options(build_mode, arg[i])
end
else
print_server_options(build_mode, arg[i])
end
else
print_server_options(build_mode, arg[i])
end
i = i + 1
end
-- Create socket for incoming connections
local server_sock = socket.try(socket.bind("*", port))
---------------------------------------------------------------------------
-- This is where the interesting stuff happens. Up until now we've
-- just been setting up sockets etc. Now we do the SSL handshake.
---------------------------------------------------------------------------
local ssl_ctx = axtlsl.ssl_ctx_new(options, axtlsl.SSL_DEFAULT_SVR_SESS)
if ssl_ctx == nil then error("Error: Server context is invalid") end
if private_key_file ~= nil then
local obj_type = axtlsl.SSL_OBJ_RSA_KEY
if string.find(private_key_file, ".p8") then
obj_type = axtlsl.SSL_OBJ_PKCS8
end
if string.find(private_key_file, ".p12") then
obj_type = axtlsl.SSL_OBJ_PKCS12
end
if axtlsl.ssl_obj_load(ssl_ctx, obj_type, private_key_file,
password) ~= axtlsl.SSL_OK then
error("Private key '" .. private_key_file .. "' is undefined.")
end
end
for _, v in ipairs(cert) do
if axtlsl.ssl_obj_load(ssl_ctx, axtlsl.SSL_OBJ_X509_CERT, v, "") ~=
axtlsl.SSL_OK then
error("Certificate '"..v .. "' is undefined.")
end
end
for _, v in ipairs(ca_cert) do
if axtlsl.ssl_obj_load(ssl_ctx, axtlsl.SSL_OBJ_X509_CACERT, v, "") ~=
axtlsl.SSL_OK then
error("Certificate '"..v .."' is undefined.")
end
end
while true do
if not quiet then print("ACCEPT") end
local client_sock = server_sock:accept();
local ssl = axtlsl.ssl_server_new(ssl_ctx, client_sock:getfd())
-- do the actual SSL handshake
local connected = false
local res
local buf
while true do
socket.select({client_sock}, nil)
res, buf = axtlsl.ssl_read(ssl)
if res == axtlsl.SSL_OK then -- connection established and ok
if axtlsl.ssl_handshake_status(ssl) == axtlsl.SSL_OK then
if not quiet and not connected then
display_session_id(ssl)
display_cipher(ssl)
end
connected = true
end
end
if res > axtlsl.SSL_OK then
for _, v in ipairs(buf) do
io.write(string.format("%c", v))
end
elseif res < axtlsl.SSL_OK then
if not quiet then
axtlsl.ssl_display_error(res)
end
break
end
end
-- client was disconnected or the handshake failed.
print("CONNECTION CLOSED")
axtlsl.ssl_free(ssl)
client_sock:close()
end
axtlsl.ssl_ctx_free(ssl_ctx)
end
--
-- Implement the SSL client logic.
--
function do_client(build_mode)
local i = 2
local v
local port = 4433
local options =
bit.bor(axtlsl.SSL_SERVER_VERIFY_LATER, axtlsl.SSL_DISPLAY_CERTS)
local private_key_file = nil
local reconnect = 0
local quiet = false
local password = ""
local session_id = {}
local host = "127.0.0.1"
local cert_size = axtlsl.ssl_get_config(axtlsl.SSL_MAX_CERT_CFG_OFFSET)
local ca_cert_size = axtlsl.
ssl_get_config(axtlsl.SSL_MAX_CA_CERT_CFG_OFFSET)
local cert = {}
local ca_cert = {}
while i <= #arg do
if arg[i] == "-connect" then
if i >= #arg then
print_client_options(build_mode, arg[i])
end
i = i + 1
local t = string.find(arg[i], ":")
host = string.sub(arg[i], 1, t-1)
port = string.sub(arg[i], t+1)
elseif arg[i] == "-cert" then
if i >= #arg or #cert >= cert_size then
print_client_options(build_mode, arg[i])
end
i = i + 1
table.insert(cert, arg[i])
elseif arg[i] == "-key" then
if i >= #arg then
print_client_options(build_mode, arg[i])
end
i = i + 1
private_key_file = arg[i]
options = bit.bor(options, axtlsl.SSL_NO_DEFAULT_KEY)
elseif arg[i] == "-CAfile" then
if i >= #arg or #ca_cert >= ca_cert_size then
print_client_options(build_mode, arg[i])
end
i = i + 1
table.insert(ca_cert, arg[i])
elseif arg[i] == "-verify" then
options = bit.band(options,
bit.bnot(axtlsl.SSL_SERVER_VERIFY_LATER))
elseif arg[i] == "-reconnect" then
reconnect = 4
elseif arg[i] == "-quiet" then
quiet = true
options = bit.band(options, bnot(axtlsl.SSL_DISPLAY_CERTS))
elseif arg[i] == "-pass" then
if i >= #arg then
print_server_options(build_mode, arg[i])
end
i = i + 1
password = arg[i]
elseif build_mode == axtlsl.SSL_BUILD_FULL_MODE then
if arg[i] == "-debug" then
options = bit.bor(options, axtlsl.SSL_DISPLAY_BYTES)
elseif arg[i] == "-state" then
options = bit.bor(axtlsl.SSL_DISPLAY_STATES)
elseif arg[i] == "-show-rsa" then
options = bit.bor(axtlsl.SSL_DISPLAY_RSA)
else -- don't know what this is
print_client_options(build_mode, arg[i])
end
else -- don't know what this is
print_client_options(build_mode, arg[i])
end
i = i + 1
end
local client_sock = socket.try(socket.connect(host, port))
local ssl
local res
if not quiet then print("CONNECTED") end
---------------------------------------------------------------------------
-- This is where the interesting stuff happens. Up until now we've
-- just been setting up sockets etc. Now we do the SSL handshake.
---------------------------------------------------------------------------
local ssl_ctx = axtlsl.ssl_ctx_new(options, axtlsl.SSL_DEFAULT_CLNT_SESS)
if ssl_ctx == nil then
error("Error: Client context is invalid")
end
if private_key_file ~= nil then
local obj_type = axtlsl.SSL_OBJ_RSA_KEY
if string.find(private_key_file, ".p8") then
obj_type = axtlsl.SSL_OBJ_PKCS8
end
if string.find(private_key_file, ".p12") then
obj_type = axtlsl.SSL_OBJ_PKCS12
end
if axtlsl.ssl_obj_load(ssl_ctx, obj_type, private_key_file,
password) ~= axtlsl.SSL_OK then
error("Private key '"..private_key_file.."' is undefined.")
end
end
for _, v in ipairs(cert) do
if axtlsl.ssl_obj_load(ssl_ctx, axtlsl.SSL_OBJ_X509_CERT, v, "") ~=
axtlsl.SSL_OK then
error("Certificate '"..v .. "' is undefined.")
end
end
for _, v in ipairs(ca_cert) do
if axtlsl.ssl_obj_load(ssl_ctx, axtlsl.SSL_OBJ_X509_CACERT, v, "") ~=
axtlsl.SSL_OK then
error("Certificate '"..v .."' is undefined.")
end
end
-- Try session resumption?
if reconnect ~= 0 then
local session_id = nil
local sess_id_size = 0
while reconnect > 0 do
reconnect = reconnect - 1
ssl = axtlsl.ssl_client_new(ssl_ctx,
client_sock:getfd(), session_id, sess_id_size)
res = axtlsl.ssl_handshake_status(ssl)
if res ~= axtlsl.SSL_OK then
if not quiet then axtlsl.ssl_display_error(res) end
axtlsl.ssl_free(ssl)
os.exit(1)
end
display_session_id(ssl)
session_id = axtlsl.ssl_get_session_id(ssl)
sess_id_size = axtlsl.ssl_get_session_id_size(ssl)
if reconnect > 0 then
axtlsl.ssl_free(ssl)
client_sock:close()
client_sock = socket.try(socket.connect(host, port))
end
end
else
ssl = axtlsl.ssl_client_new(ssl_ctx, client_sock:getfd(), nil, 0)
end
-- check the return status
res = axtlsl.ssl_handshake_status(ssl)
if res ~= axtlsl.SSL_OK then
if not quiet then axtlsl.ssl_display_error(res) end
os.exit(1)
end
if not quiet then
local common_name = axtlsl.ssl_get_cert_dn(ssl,
axtlsl.SSL_X509_CERT_COMMON_NAME)
if common_name ~= nil then
print("Common Name:\t\t\t"..common_name)
end
display_session_id(ssl)
display_cipher(ssl)
end
while true do
local line = io.read()
if line == nil then break end
local bytes = {}
for i = 1, #line do
bytes[i] = line.byte(line, i)
end
bytes[#line+1] = 10 -- add carriage return, null
bytes[#line+2] = 0
res = axtlsl.ssl_write(ssl, bytes, #bytes)
if res < axtlsl.SSL_OK then
if not quiet then axtlsl.ssl_display_error(res) end
break
end
end
axtlsl.ssl_ctx_free(ssl_ctx)
client_sock:close()
end
--
-- Display what cipher we are using
--
function display_cipher(ssl)
io.write("CIPHER is ")
local cipher_id = axtlsl.ssl_get_cipher_id(ssl)
if cipher_id == axtlsl.SSL_AES128_SHA then
print("AES128-SHA")
elseif cipher_id == axtlsl.SSL_AES256_SHA then
print("AES256-SHA")
elseif axtlsl.SSL_AES128_SHA256 then
print("AES128-SHA256")
elseif axtlsl.SSL_AES256_SHA256 then
print("AES256-SHA256")
else
print("Unknown - "..cipher_id)
end
end
--
-- Display what session id we have.
--
function display_session_id(ssl)
local session_id = axtlsl.ssl_get_session_id(ssl)
local v
if #session_id > 0 then
print("-----BEGIN SSL SESSION PARAMETERS-----")
for _, v in ipairs(session_id) do
io.write(string.format("%02x", v))
end
print("\n-----END SSL SESSION PARAMETERS-----")
end
end
--
-- Main entry point. Doesn't do much except works out whether we are a client
-- or a server.
--
if #arg == 0 or (arg[1] ~= "s_server" and arg[1] ~= "s_client") then
print_options(#arg > 0 and arg[1] or "")
end
local build_mode = axtlsl.ssl_get_config(axtlsl.SSL_BUILD_MODE)
_ = arg[1] == "s_server" and do_server(build_mode) or do_client(build_mode)
os.exit(0)

634
samples/perl/axssl.pl Executable file
View File

@@ -0,0 +1,634 @@
#!/usr/bin/perl -w
#
# Copyright (c) 2007-2016, Cameron Rich
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Demonstrate the use of the axTLS library in Perl with a set of
# command-line parameters similar to openssl. In fact, openssl clients
# should be able to communicate with axTLS servers and visa-versa.
#
# This code has various bits enabled depending on the configuration. To enable
# the most interesting version, compile with the 'full mode' enabled.
#
# To see what options you have, run the following:
# > [perl] axssl s_server -?
# > [perl] axssl s_client -?
#
# The axtls/axtlsp shared libraries must be in the same directory or be found
# by the OS. axtlsp.pm must be in this directory or be in @INC.
#
# Under Win32, ActivePerl was used (see
# http://www.activestate.com/Products/ActivePerl/?mp=1)
#
use axtlsp;
use IO::Socket;
# To get access to Win32 file descriptor stuff
my $is_win32 = 0;
if ($^O eq "MSWin32")
{
eval("use Win32API::File 0.08 qw( :ALL )");
$is_win32 = 1;
}
use strict;
#
# Win32 has some problems with socket handles
#
sub get_native_sock
{
my ($sock) = @_;
return $is_win32 ? FdGetOsFHandle($sock) : $sock;
}
# print version?
if ($#ARGV == 0 && $ARGV[0] eq "version")
{
printf("axssl.pl ".axtlsp::ssl_version()."\n");
exit 0;
}
#
# Main entry point. Doesn't do much except works out whether we are a client
# or a server.
#
print_options($#ARGV > -1 ? $ARGV[0] : "")
if ($#ARGV < 0 || ($ARGV[0] ne "s_server" && $ARGV[0] ne "s_client"));
# Cygwin/Win32 issue - flush our output continuously
select STDOUT;
local $|=1;
my $build_mode = axtlsp::ssl_get_config($axtlsp::SSL_BUILD_MODE);
$ARGV[0] eq "s_server" ? do_server($build_mode) : do_client($build_mode);
#
# Implement the SSL server logic.
#
sub do_server
{
my ($build_mode) = @_;
my $i = 1;
my $port = 4433;
my $options = $axtlsp::SSL_DISPLAY_CERTS;
my $quiet = 0;
my $password = undef;
my $private_key_file = undef;
my $cert_size = axtlsp::ssl_get_config($axtlsp::SSL_MAX_CERT_CFG_OFFSET);
my $ca_cert_size = axtlsp::ssl_get_config(
$axtlsp::SSL_MAX_CA_CERT_CFG_OFFSET);
my @cert;
my @ca_cert;
while ($i <= $#ARGV)
{
if ($ARGV[$i] eq "-accept")
{
print_server_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
$port = $ARGV[++$i];
}
elsif ($ARGV[$i] eq "-quiet")
{
$quiet = 1;
$options &= ~$axtlsp::SSL_DISPLAY_CERTS;
}
elsif ($build_mode >= $axtlsp::SSL_BUILD_SERVER_ONLY)
{
if ($ARGV[$i] eq "-cert")
{
print_server_options($build_mode, $ARGV[$i])
if $i >= $#ARGV || $#cert >= $cert_size-1;
push @cert, $ARGV[++$i];
}
elsif ($ARGV[$i] eq "-key")
{
print_server_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
$private_key_file = $ARGV[++$i];
$options |= $axtlsp::SSL_NO_DEFAULT_KEY;
}
elsif ($ARGV[$i] eq "-pass")
{
print_server_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
$password = $ARGV[++$i];
}
elsif ($build_mode >= $axtlsp::SSL_BUILD_ENABLE_VERIFICATION)
{
if ($ARGV[$i] eq "-verify")
{
$options |= $axtlsp::SSL_CLIENT_AUTHENTICATION;
}
elsif ($ARGV[$i] eq "-CAfile")
{
print_server_options($build_mode, $ARGV[$i])
if $i >= $#ARGV || $#ca_cert >= $ca_cert_size-1;
push @ca_cert, $ARGV[++$i];
}
elsif ($build_mode == $axtlsp::SSL_BUILD_FULL_MODE)
{
if ($ARGV[$i] eq "-debug")
{
$options |= $axtlsp::SSL_DISPLAY_BYTES;
}
elsif ($ARGV[$i] eq "-state")
{
$options |= $axtlsp::SSL_DISPLAY_STATES;
}
elsif ($ARGV[$i] eq "-show-rsa")
{
$options |= $axtlsp::SSL_DISPLAY_RSA;
}
else
{
print_server_options($build_mode, $ARGV[$i]);
}
}
else
{
print_server_options($build_mode, $ARGV[$i]);
}
}
else
{
print_server_options($build_mode, $ARGV[$i]);
}
}
else
{
print_server_options($build_mode, $ARGV[$i]);
}
$i++;
}
# Create socket for incoming connections
my $server_sock = IO::Socket::INET->new(Proto => 'tcp',
LocalPort => $port,
Listen => 1,
Reuse => 1) or die $!;
###########################################################################
# This is where the interesting stuff happens. Up until now we've
# just been setting up sockets etc. Now we do the SSL handshake.
###########################################################################
my $ssl_ctx = axtlsp::ssl_ctx_new($options, $axtlsp::SSL_DEFAULT_SVR_SESS);
die "Error: Server context is invalid" if not defined $ssl_ctx;
if (defined $private_key_file)
{
my $obj_type = $axtlsp::SSL_OBJ_RSA_KEY;
$obj_type = $axtlsp::SSL_OBJ_PKCS8 if $private_key_file =~ /.p8$/;
$obj_type = $axtlsp::SSL_OBJ_PKCS12 if $private_key_file =~ /.p12$/;
die "Private key '$private_key_file' is undefined." if
axtlsp::ssl_obj_load($ssl_ctx, $obj_type,
$private_key_file, $password);
}
foreach (@cert)
{
die "Certificate '$_' is undefined."
if axtlsp::ssl_obj_load($ssl_ctx, $axtlsp::SSL_OBJ_X509_CERT,
$_, undef) != $axtlsp::SSL_OK;
}
foreach (@ca_cert)
{
die "Certificate '$_' is undefined."
if axtlsp::ssl_obj_load($ssl_ctx, $axtlsp::SSL_OBJ_X509_CACERT,
$_, undef) != $axtlsp::SSL_OK;
}
for (;;)
{
printf("ACCEPT\n") if not $quiet;
my $client_sock = $server_sock->accept;
my $native_sock = get_native_sock($client_sock->fileno);
# This doesn't work in Win32 - need to get file descriptor from socket.
my $ssl = axtlsp::ssl_server_new($ssl_ctx, $native_sock);
# do the actual SSL handshake
my $res;
my $buf;
my $connected = 0;
while (1)
{
($res, $buf) = axtlsp::ssl_read($ssl, undef);
last if $res < $axtlsp::SSL_OK;
if ($res == $axtlsp::SSL_OK) # connection established and ok
{
if (axtlsp::ssl_handshake_status($ssl) == $axtlsp::SSL_OK)
{
if (!$quiet && !$connected)
{
display_session_id($ssl);
display_cipher($ssl);
}
$connected = 1;
}
}
if ($res > $axtlsp::SSL_OK)
{
printf($$buf);
}
elsif ($res < $axtlsp::SSL_OK)
{
axtlsp::ssl_display_error($res) if not $quiet;
last;
}
}
# client was disconnected or the handshake failed.
printf("CONNECTION CLOSED\n") if not $quiet;
axtlsp::ssl_free($ssl);
$client_sock->close;
}
axtlsp::ssl_ctx_free($ssl_ctx);
}
#
# Implement the SSL client logic.
#
sub do_client
{
my ($build_mode) = @_;
my $i = 1;
my $port = 4433;
my $options = $axtlsp::SSL_SERVER_VERIFY_LATER|$axtlsp::SSL_DISPLAY_CERTS;
my $private_key_file = undef;
my $reconnect = 0;
my $quiet = 0;
my $password = undef;
my @session_id;
my $host = "127.0.0.1";
my @cert;
my @ca_cert;
my $cert_size = axtlsp::ssl_get_config(
$axtlsp::SSL_MAX_CERT_CFG_OFFSET);
my $ca_cert_size = axtlsp::ssl_get_config(
$axtlsp::SSL_MAX_CA_CERT_CFG_OFFSET);
while ($i <= $#ARGV)
{
if ($ARGV[$i] eq "-connect")
{
print_client_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
($host, $port) = split(':', $ARGV[++$i]);
}
elsif ($ARGV[$i] eq "-cert")
{
print_client_options($build_mode, $ARGV[$i])
if $i >= $#ARGV || $#cert >= $cert_size-1;
push @cert, $ARGV[++$i];
}
elsif ($ARGV[$i] eq "-key")
{
print_client_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
$private_key_file = $ARGV[++$i];
$options |= $axtlsp::SSL_NO_DEFAULT_KEY;
}
elsif ($ARGV[$i] eq "-CAfile")
{
print_client_options($build_mode, $ARGV[$i])
if $i >= $#ARGV || $#ca_cert >= $ca_cert_size-1;
push @ca_cert, $ARGV[++$i];
}
elsif ($ARGV[$i] eq "-verify")
{
$options &= ~$axtlsp::SSL_SERVER_VERIFY_LATER;
}
elsif ($ARGV[$i] eq "-reconnect")
{
$reconnect = 4;
}
elsif ($ARGV[$i] eq "-quiet")
{
$quiet = 1;
$options &= ~$axtlsp::SSL_DISPLAY_CERTS;
}
elsif ($ARGV[$i] eq "-pass")
{
print_server_options($build_mode, $ARGV[$i]) if $i >= $#ARGV;
$password = $ARGV[++$i];
}
elsif ($build_mode == $axtlsp::SSL_BUILD_FULL_MODE)
{
if ($ARGV[$i] eq "-debug")
{
$options |= $axtlsp::SSL_DISPLAY_BYTES;
}
elsif ($ARGV[$i] eq "-state")
{
$options |= $axtlsp::SSL_DISPLAY_STATES;
}
elsif ($ARGV[$i] eq "-show-rsa")
{
$options |= $axtlsp::SSL_DISPLAY_RSA;
}
else # don't know what this is
{
print_client_options($build_mode, $ARGV[$i]);
}
}
else # don't know what this is
{
print_client_options($build_mode, $ARGV[$i]);
}
$i++;
}
my $client_sock = new IO::Socket::INET (
PeerAddr => $host, PeerPort => $port, Proto => 'tcp')
|| die ("no socket: $!");
my $ssl;
my $res;
my $native_sock = get_native_sock($client_sock->fileno);
printf("CONNECTED\n") if not $quiet;
###########################################################################
# This is where the interesting stuff happens. Up until now we've
# just been setting up sockets etc. Now we do the SSL handshake.
###########################################################################
my $ssl_ctx = axtlsp::ssl_ctx_new($options, $axtlsp::SSL_DEFAULT_CLNT_SESS);
die "Error: Client context is invalid" if not defined $ssl_ctx;
if (defined $private_key_file)
{
my $obj_type = $axtlsp::SSL_OBJ_RSA_KEY;
$obj_type = $axtlsp::SSL_OBJ_PKCS8 if $private_key_file =~ /.p8$/;
$obj_type = $axtlsp::SSL_OBJ_PKCS12 if $private_key_file =~ /.p12$/;
die "Private key '$private_key_file' is undefined." if
axtlsp::ssl_obj_load($ssl_ctx, $obj_type,
$private_key_file, $password);
}
foreach (@cert)
{
die "Certificate '$_' is undefined."
if axtlsp::ssl_obj_load($ssl_ctx, $axtlsp::SSL_OBJ_X509_CERT,
$_, undef) != $axtlsp::SSL_OK;
}
foreach (@ca_cert)
{
die "Certificate '$_' is undefined."
if axtlsp::ssl_obj_load($ssl_ctx, $axtlsp::SSL_OBJ_X509_CACERT,
$_, undef) != $axtlsp::SSL_OK;
}
# Try session resumption?
if ($reconnect)
{
my $session_id = undef;
my $sess_id_size = 0;
while ($reconnect--)
{
$ssl = axtlsp::ssl_client_new($ssl_ctx, $native_sock,
$session_id, $sess_id_size);
$res = axtlsp::ssl_handshake_status($ssl);
if ($res != $axtlsp::SSL_OK)
{
axtlsp::ssl_display_error($res) if !$quiet;
axtlsp::ssl_free($ssl);
exit 1;
}
display_session_id($ssl);
$session_id = axtlsp::ssl_get_session_id($ssl);
if ($reconnect)
{
axtlsp::ssl_free($ssl);
$client_sock->close;
$client_sock = new IO::Socket::INET (
PeerAddr => $host, PeerPort => $port, Proto => 'tcp')
|| die ("no socket: $!");
}
}
}
else
{
$ssl = axtlsp::ssl_client_new($ssl_ctx, $native_sock, undef, 0);
}
# check the return status
$res = axtlsp::ssl_handshake_status($ssl);
if ($res != $axtlsp::SSL_OK)
{
axtlsp::ssl_display_error($res) if not $quiet;
exit 1;
}
if (!$quiet)
{
my $common_name = axtlsp::ssl_get_cert_dn($ssl,
$axtlsp::SSL_X509_CERT_COMMON_NAME);
printf("Common Name:\t\t\t%s\n", $common_name) if defined $common_name;
display_session_id($ssl);
display_cipher($ssl);
}
while (<STDIN>)
{
my $cstring = pack("a*x", $_); # add null terminator
$res = axtlsp::ssl_write($ssl, \$cstring, length($cstring));
if ($res < $axtlsp::SSL_OK)
{
axtlsp::ssl_display_error($res) if not $quiet;
last;
}
}
axtlsp::ssl_ctx_free($ssl_ctx);
$client_sock->close;
}
#
# We've had some sort of command-line error. Print out the basic options.
#
sub print_options
{
my ($option) = @_;
printf("axssl: Error: '%s' is an invalid command.\n", $option);
printf("usage: axssl [s_server|s_client|version] [args ...]\n");
exit 1;
}
#
# We've had some sort of command-line error. Print out the server options.
#
sub print_server_options
{
my ($build_mode, $option) = @_;
my $cert_size = axtlsp::ssl_get_config($axtlsp::SSL_MAX_CERT_CFG_OFFSET);
my $ca_cert_size = axtlsp::ssl_get_config(
$axtlsp::SSL_MAX_CA_CERT_CFG_OFFSET);
printf("unknown option %s\n", $option);
printf("usage: s_server [args ...]\n");
printf(" -accept arg\t- port to accept on (default is 4433)\n");
printf(" -quiet\t\t- No server output\n");
if ($build_mode >= $axtlsp::SSL_BUILD_SERVER_ONLY)
{
printf(" -cert arg\t- certificate file to add (in addition to default)".
" to chain -\n".
"\t\t Can repeat up to %d times\n", $cert_size);
printf(" -key arg\t- Private key file to use - default DER format\n");
printf(" -pass\t\t- private key file pass phrase source\n");
}
if ($build_mode >= $axtlsp::SSL_BUILD_ENABLE_VERIFICATION)
{
printf(" -verify\t- turn on peer certificate verification\n");
printf(" -CAfile arg\t- Certificate authority - default DER format\n");
printf("\t\t Can repeat up to %d times\n", $ca_cert_size);
}
if ($build_mode == $axtlsp::SSL_BUILD_FULL_MODE)
{
printf(" -debug\t\t- Print more output\n");
printf(" -state\t\t- Show state messages\n");
printf(" -show-rsa\t- Show RSA state\n");
}
exit 1;
}
#
# We've had some sort of command-line error. Print out the client options.
#
sub print_client_options
{
my ($build_mode, $option) = @_;
my $cert_size = axtlsp::ssl_get_config($axtlsp::SSL_MAX_CERT_CFG_OFFSET);
my $ca_cert_size = axtlsp::ssl_get_config(
$axtlsp::SSL_MAX_CA_CERT_CFG_OFFSET);
printf("unknown option %s\n", $option);
if ($build_mode >= $axtlsp::SSL_BUILD_ENABLE_CLIENT)
{
printf("usage: s_client [args ...]\n");
printf(" -connect host:port - who to connect to (default ".
"is localhost:4433)\n");
printf(" -verify\t- turn on peer certificate verification\n");
printf(" -cert arg\t- certificate file to use - default DER format\n");
printf(" -key arg\t- Private key file to use - default DER format\n");
printf("\t\t Can repeat up to %d times\n", $cert_size);
printf(" -CAfile arg\t- Certificate authority - default DER format\n");
printf("\t\t Can repeat up to %d times\n", $ca_cert_size);
printf(" -quiet\t\t- No client output\n");
printf(" -pass\t\t- private key file pass phrase source\n");
printf(" -reconnect\t- Drop and re-make the connection ".
"with the same Session-ID\n");
if ($build_mode == $axtlsp::SSL_BUILD_FULL_MODE)
{
printf(" -debug\t\t- Print more output\n");
printf(" -state\t\t- Show state messages\n");
printf(" -show-rsa\t- Show RSA state\n");
}
}
else
{
printf("Change configuration to allow this feature\n");
}
exit 1;
}
#
# Display what cipher we are using
#
sub display_cipher
{
my ($ssl) = @_;
printf("CIPHER is ");
my $cipher_id = axtlsp::ssl_get_cipher_id($ssl);
if ($cipher_id == $axtlsp::SSL_AES128_SHA)
{
printf("AES128-SHA");
}
elsif ($cipher_id == $axtlsp::SSL_AES256_SHA)
{
printf("AES256-SHA");
}
elsif ($axtlsp::SSL_AES128_SHA256)
{
printf("AES128-SHA256");
}
elsif ($axtlsp::SSL_AES256_SHA256)
{
printf("AES256-SHA256");
}
else
{
printf("Unknown - %d", $cipher_id);
}
printf("\n");
}
#
# Display what session id we have.
#
sub display_session_id
{
my ($ssl) = @_;
my $session_id = axtlsp::ssl_get_session_id($ssl);
if (length($$session_id) > 0)
{
printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
printf(unpack("H*", $$session_id));
printf("\n-----END SSL SESSION PARAMETERS-----\n");
}
}

702
samples/vbnet/axssl.vb Normal file
View File

@@ -0,0 +1,702 @@
'
' Copyright (c) 2007-2016, Cameron Rich
'
' All rights reserved.
'
' Redistribution and use in source and binary forms, with or without
' modification, are permitted provided that the following conditions are met:
'
' * Redistributions of source code must retain the above copyright notice,
' this list of conditions and the following disclaimer.
' * Redistributions in binary form must reproduce the above copyright
' notice, this list of conditions and the following disclaimer in the
' documentation and/or other materials provided with the distribution.
' * Neither the name of the axTLS project nor the names of its
' contributors may be used to endorse or promote products derived
' from this software without specific prior written permission.
'
' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
' "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
' LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
' A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
' CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
' SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
' TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
' DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
' OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
' NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
' THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'
'
' Demonstrate the use of the axTLS library in VB.NET with a set of
' command-line parameters similar to openssl. In fact, openssl clients
' should be able to communicate with axTLS servers and visa-versa.
'
' This code has various bits enabled depending on the configuration. To enable
' the most interesting version, compile with the 'full mode' enabled.
'
' To see what options you have, run the following:
' > axssl.vbnet.exe s_server -?
' > axssl.vbnet.exe s_client -?
'
' The axtls shared library must be in the same directory or be found
' by the OS.
'
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports Microsoft.VisualBasic
Imports axTLSvb
Public Class axssl
'
' do_server()
'
Public Sub do_server(ByVal build_mode As Integer, _
ByVal args() As String)
Dim i As Integer = 1
Dim port As Integer = 4433
Dim options As Integer = axtls.SSL_DISPLAY_CERTS
Dim quiet As Boolean = False
Dim password As String = Nothing
Dim private_key_file As String = Nothing
' organise the cert/ca_cert lists
Dim cert_size As Integer = SSLUtil.MaxCerts()
Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
Dim cert(cert_size) As String
Dim ca_cert(ca_cert_size) As String
Dim cert_index As Integer = 0
Dim ca_cert_index As Integer = 0
While i < args.Length
If args(i) = "-accept" Then
If i >= args.Length-1
print_server_options(build_mode, args(i))
End If
i += 1
port = Int32.Parse(args(i))
ElseIf args(i) = "-quiet"
quiet = True
options = options And Not axtls.SSL_DISPLAY_CERTS
ElseIf build_mode >= axtls.SSL_BUILD_SERVER_ONLY
If args(i) = "-cert"
If i >= args.Length-1 Or cert_index >= cert_size
print_server_options(build_mode, args(i))
End If
i += 1
cert(cert_index) = args(i)
cert_index += 1
ElseIf args(i) = "-key"
If i >= args.Length-1
print_server_options(build_mode, args(i))
End If
i += 1
private_key_file = args(i)
options = options Or axtls.SSL_NO_DEFAULT_KEY
ElseIf args(i) = "-pass"
If i >= args.Length-1
print_server_options(build_mode, args(i))
End If
i += 1
password = args(i)
ElseIf build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION
If args(i) = "-verify" Then
options = options Or axtls.SSL_CLIENT_AUTHENTICATION
ElseIf args(i) = "-CAfile"
If i >= args.Length-1 Or _
ca_cert_index >= ca_cert_size Then
print_server_options(build_mode, args(i))
End If
i += 1
ca_cert(ca_cert_index) = args(i)
ca_cert_index += 1
ElseIf build_mode = axtls.SSL_BUILD_FULL_MODE
If args(i) = "-debug" Then
options = options Or axtls.SSL_DISPLAY_BYTES
ElseIf args(i) = "-state"
options = options Or axtls.SSL_DISPLAY_STATES
ElseIf args(i) = "-show-rsa"
options = options Or axtls.SSL_DISPLAY_RSA
Else
print_server_options(build_mode, args(i))
End If
Else
print_server_options(build_mode, args(i))
End If
Else
print_server_options(build_mode, args(i))
End If
End If
i += 1
End While
' Create socket for incoming connections
Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, port)
Dim server_sock As TcpListener = New TcpListener(ep)
server_sock.Start()
'*********************************************************************
' This is where the interesting stuff happens. Up until now we've
' just been setting up sockets etc. Now we do the SSL handshake.
'*********************************************************************/
Dim ssl_ctx As SSLServer = New SSLServer(options, _
axtls.SSL_DEFAULT_SVR_SESS)
If ssl_ctx Is Nothing Then
Console.Error.WriteLine("Error: Server context is invalid")
Environment.Exit(1)
End If
If private_key_file <> Nothing Then
Dim obj_type As Integer = axtls.SSL_OBJ_RSA_KEY
If private_key_file.EndsWith(".p8") Then
obj_type = axtls.SSL_OBJ_PKCS8
Else If (private_key_file.EndsWith(".p12"))
obj_type = axtls.SSL_OBJ_PKCS12
End If
If ssl_ctx.ObjLoad(obj_type, private_key_file, _
password) <> axtls.SSL_OK Then
Console.Error.WriteLine("Error: Private key '" & _
private_key_file & "' is undefined.")
Environment.Exit(1)
End If
End If
For i = 0 To cert_index-1
If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT, _
cert(i), Nothing) <> axtls.SSL_OK Then
Console.WriteLine("Certificate '" & cert(i) & _
"' is undefined.")
Environment.Exit(1)
End If
Next
For i = 0 To ca_cert_index-1
If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT, _
ca_cert(i), Nothing) <> axtls.SSL_OK Then
Console.WriteLine("Certificate '" & ca_cert(i) & _
"' is undefined.")
Environment.Exit(1)
End If
Next
Dim buf As Byte() = Nothing
Dim res As Integer
Dim ssl As SSL
While 1
If Not quiet Then
Console.WriteLine("ACCEPT")
End If
Dim client_sock As Socket = server_sock.AcceptSocket()
ssl = ssl_ctx.Connect(client_sock)
' do the actual SSL handshake
While 1
res = ssl_ctx.Read(ssl, buf)
If res <> axtls.SSL_OK Then
Exit While
End If
' check when the connection has been established
If ssl.HandshakeStatus() = axtls.SSL_OK
Exit While
End If
' could do something else here
End While
If res = axtls.SSL_OK Then ' connection established and ok
If Not quiet
display_session_id(ssl)
display_cipher(ssl)
End If
' now read (and display) whatever the client sends us
While 1
' keep reading until we get something interesting
While 1
res = ssl_ctx.Read(ssl, buf)
If res <> axtls.SSL_OK Then
Exit While
End If
' could do something else here
End While
If res < axtls.SSL_OK
If Not quiet
Console.WriteLine("CONNECTION CLOSED")
End If
Exit While
End If
' convert to String
Dim str(res) As Char
For i = 0 To res-1
str(i) = Chr(buf(i))
Next
Console.Write(str)
End While
ElseIf Not quiet
SSLUtil.DisplayError(res)
End If
' client was disconnected or the handshake failed. */
ssl.Dispose()
client_sock.Close()
End While
ssl_ctx.Dispose()
End Sub
'
' do_client()
'
Public Sub do_client(ByVal build_mode As Integer, _
ByVal args() As String)
If build_mode < axtls.SSL_BUILD_ENABLE_CLIENT Then
print_client_options(build_mode, args(1))
End If
Dim i As Integer = 1
Dim res As Integer
Dim port As Integer = 4433
Dim quiet As Boolean = False
Dim password As String = Nothing
Dim reconnect As Integer = 0
Dim private_key_file As String = Nothing
Dim hostname As String = "127.0.0.1"
' organise the cert/ca_cert lists
Dim ssl As SSL = Nothing
Dim cert_size As Integer = SSLUtil.MaxCerts()
Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
Dim cert(cert_size) As String
Dim ca_cert(ca_cert_size) As String
Dim cert_index As Integer = 0
Dim ca_cert_index As Integer = 0
Dim options As Integer = _
axtls.SSL_SERVER_VERIFY_LATER Or axtls.SSL_DISPLAY_CERTS
Dim session_id As Byte() = Nothing
While i < args.Length
If args(i) = "-connect" Then
Dim host_port As String
If i >= args.Length-1
print_client_options(build_mode, args(i))
End If
i += 1
host_port = args(i)
Dim index_colon As Integer = host_port.IndexOf(":"C)
If index_colon < 0 Then
print_client_options(build_mode, args(i))
End If
hostname = New String(host_port.ToCharArray(), _
0, index_colon)
port = Int32.Parse(New String(host_port.ToCharArray(), _
index_colon+1, host_port.Length-index_colon-1))
ElseIf args(i) = "-cert"
If i >= args.Length-1 Or cert_index >= cert_size Then
print_client_options(build_mode, args(i))
End If
i += 1
cert(cert_index) = args(i)
cert_index += 1
ElseIf args(i) = "-key"
If i >= args.Length-1
print_client_options(build_mode, args(i))
End If
i += 1
private_key_file = args(i)
options = options Or axtls.SSL_NO_DEFAULT_KEY
ElseIf args(i) = "-CAfile"
If i >= args.Length-1 Or ca_cert_index >= ca_cert_size
print_client_options(build_mode, args(i))
End If
i += 1
ca_cert(ca_cert_index) = args(i)
ca_cert_index += 1
ElseIf args(i) = "-verify"
options = options And Not axtls.SSL_SERVER_VERIFY_LATER
ElseIf args(i) = "-reconnect"
reconnect = 4
ElseIf args(i) = "-quiet"
quiet = True
options = options And Not axtls.SSL_DISPLAY_CERTS
ElseIf args(i) = "-pass"
If i >= args.Length-1
print_client_options(build_mode, args(i))
End If
i += 1
password = args(i)
ElseIf build_mode = axtls.SSL_BUILD_FULL_MODE
If args(i) = "-debug" Then
options = options Or axtls.SSL_DISPLAY_BYTES
ElseIf args(i) = "-state"
options = options Or axtls.SSL_DISPLAY_STATES
ElseIf args(i) = "-show-rsa"
options = options Or axtls.SSL_DISPLAY_RSA
Else
print_client_options(build_mode, args(i))
End If
Else ' don't know what this is
print_client_options(build_mode, args(i))
End If
i += 1
End While
'Dim hostInfo As IPHostEntry = Dns.Resolve(hostname)
Dim hostInfo As IPHostEntry = Dns.GetHostEntry(hostname)
Dim addresses As IPAddress() = hostInfo.AddressList
Dim ep As IPEndPoint = New IPEndPoint(addresses(0), port)
Dim client_sock As Socket = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
client_sock.Connect(ep)
If Not client_sock.Connected Then
Console.WriteLine("could not connect")
Environment.Exit(1)
End If
If Not quiet Then
Console.WriteLine("CONNECTED")
End If
'*********************************************************************
' This is where the interesting stuff happens. Up until now we've
' just been setting up sockets etc. Now we do the SSL handshake.
'*********************************************************************/
Dim ssl_ctx As SSLClient = New SSLClient(options, _
axtls.SSL_DEFAULT_CLNT_SESS)
If ssl_ctx Is Nothing Then
Console.Error.WriteLine("Error: Client context is invalid")
Environment.Exit(1)
End If
If private_key_file <> Nothing Then
Dim obj_type As Integer = axtls.SSL_OBJ_RSA_KEY
If private_key_file.EndsWith(".p8") Then
obj_type = axtls.SSL_OBJ_PKCS8
Else If (private_key_file.EndsWith(".p12"))
obj_type = axtls.SSL_OBJ_PKCS12
End If
If ssl_ctx.ObjLoad(obj_type, private_key_file, _
password) <> axtls.SSL_OK Then
Console.Error.WriteLine("Error: Private key '" & _
private_key_file & "' is undefined.")
Environment.Exit(1)
End If
End If
For i = 0 To cert_index-1
If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT, _
cert(i), Nothing) <> axtls.SSL_OK Then
Console.WriteLine("Certificate '" & cert(i) & _
"' is undefined.")
Environment.Exit(1)
End If
Next
For i = 0 To ca_cert_index-1
If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT, _
ca_cert(i), Nothing) <> axtls.SSL_OK Then
Console.WriteLine("Certificate '" & ca_cert(i) & _
"' is undefined.")
Environment.Exit(1)
End If
Next
' Try session resumption?
If reconnect > 0 Then
While reconnect > 0
reconnect -= 1
ssl = ssl_ctx.Connect(client_sock, session_id)
res = ssl.HandshakeStatus()
If res <> axtls.SSL_OK Then
If Not quiet Then
SSLUtil.DisplayError(res)
End If
ssl.Dispose()
Environment.Exit(1)
End If
display_session_id(ssl)
session_id = ssl.GetSessionId()
If reconnect > 0 Then
ssl.Dispose()
client_sock.Close()
' and reconnect
client_sock = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
client_sock.Connect(ep)
End If
End While
Else
ssl = ssl_ctx.Connect(client_sock, Nothing)
End If
' check the return status
res = ssl.HandshakeStatus()
If res <> axtls.SSL_OK Then
If Not quiet Then
SSLUtil.DisplayError(res)
End If
Environment.Exit(1)
End If
If Not quiet Then
Dim common_name As String = _
ssl.GetCertificateDN(axtls.SSL_X509_CERT_COMMON_NAME)
If common_name <> Nothing
Console.WriteLine("Common Name:" & _
ControlChars.Tab & ControlChars.Tab & _
ControlChars.Tab & common_name)
End If
display_session_id(ssl)
display_cipher(ssl)
End If
While (1)
Dim user_input As String = Console.ReadLine()
If user_input = Nothing Then
Exit While
End If
Dim buf(user_input.Length+1) As Byte
buf(buf.Length-2) = Asc(ControlChars.Lf) ' add the carriage return
buf(buf.Length-1) = 0 ' null terminate
For i = 0 To user_input.Length-1
buf(i) = Asc(user_input.Chars(i))
Next
res = ssl_ctx.Write(ssl, buf, buf.Length)
If res < axtls.SSL_OK Then
If Not quiet Then
SSLUtil.DisplayError(res)
End If
Exit While
End If
End While
ssl_ctx.Dispose()
End Sub
'
' Display what cipher we are using
'
Private Sub display_cipher(ByVal ssl As SSL)
Console.Write("CIPHER is ")
Select ssl.GetCipherId()
Case axtls.SSL_AES128_SHA
Console.WriteLine("AES128-SHA")
Case axtls.SSL_AES256_SHA
Console.WriteLine("AES256-SHA")
Case axtls.SSL_AES128_SHA256
Console.WriteLine("AES128-SHA256")
Case axtls.SSL_AES256_SHA256
Console.WriteLine("AES256-SHA256")
Case Else
Console.WriteLine("Unknown - " & ssl.GetCipherId())
End Select
End Sub
'
' Display what session id we have.
'
Private Sub display_session_id(ByVal ssl As SSL)
Dim session_id As Byte() = ssl.GetSessionId()
If session_id.Length > 0 Then
Console.WriteLine("-----BEGIN SSL SESSION PARAMETERS-----")
Dim b As Byte
For Each b In session_id
Console.Write("{0:x02}", b)
Next
Console.WriteLine()
Console.WriteLine("-----END SSL SESSION PARAMETERS-----")
End If
End Sub
'
' We've had some sort of command-line error. Print out the basic options.
'
Public Sub print_options(ByVal options As String)
Console.WriteLine("axssl: Error: '" & options & _
"' is an invalid command.")
Console.WriteLine("usage: axssl.vbnet [s_server|s_client|" & _
"version] [args ...]")
Environment.Exit(1)
End Sub
'
' We've had some sort of command-line error. Print out the server options.
'
Private Sub print_server_options(ByVal build_mode As Integer, _
ByVal options As String)
Dim cert_size As Integer = SSLUtil.MaxCerts()
Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
Console.WriteLine("unknown option " & options)
Console.WriteLine("usage: s_server [args ...]")
Console.WriteLine(" -accept arg" & ControlChars.Tab & _
"- port to accept on (default is 4433)")
Console.WriteLine(" -quiet" & ControlChars.Tab & ControlChars.Tab & _
"- No server output")
If build_mode >= axtls.SSL_BUILD_SERVER_ONLY
Console.WriteLine(" -cert arg" & ControlChars.Tab & _
"- certificate file to add (in addition to default) to chain -")
Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
" Can repeat up to " & cert_size & " times")
Console.WriteLine(" -key arg" & ControlChars.Tab & _
"- Private key file to use")
Console.WriteLine(" -pass" & ControlChars.Tab & ControlChars.Tab & _
"- private key file pass phrase source")
End If
If build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION
Console.WriteLine(" -verify" & ControlChars.Tab & _
"- turn on peer certificate verification")
Console.WriteLine(" -CAfile arg" & ControlChars.Tab & _
"- Certificate authority")
Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
" Can repeat up to " & ca_cert_size & " times")
End If
If build_mode = axtls.SSL_BUILD_FULL_MODE
Console.WriteLine(" -debug" & _
ControlChars.Tab & ControlChars.Tab & _
"- Print more output")
Console.WriteLine(" -state" & _
ControlChars.Tab & ControlChars.Tab & _
"- Show state messages")
Console.WriteLine(" -show-rsa" & _
ControlChars.Tab & "- Show RSA state")
End If
Environment.Exit(1)
End Sub
'
' We've had some sort of command-line error. Print out the client options.
'
Private Sub print_client_options(ByVal build_mode As Integer, _
ByVal options As String)
Dim cert_size As Integer = SSLUtil.MaxCerts()
Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
Console.WriteLine("unknown option " & options)
If build_mode >= axtls.SSL_BUILD_ENABLE_CLIENT Then
Console.WriteLine("usage: s_client [args ...]")
Console.WriteLine(" -connect host:port - who to connect to " & _
"(default is localhost:4433)")
Console.WriteLine(" -verify" & ControlChars.Tab & _
"- turn on peer certificate verification")
Console.WriteLine(" -cert arg" & ControlChars.Tab & _
"- certificate file to use")
Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
" Can repeat up to " & cert_size & " times")
Console.WriteLine(" -key arg" & ControlChars.Tab & _
"- Private key file to use")
Console.WriteLine(" -CAfile arg" & ControlChars.Tab & _
"- Certificate authority")
Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
" Can repeat up to " & ca_cert_size & " times")
Console.WriteLine(" -quiet" & _
ControlChars.Tab & ControlChars.Tab & "- No client output")
Console.WriteLine(" -pass" & ControlChars.Tab & _
ControlChars.Tab & _
"- private key file pass phrase source")
Console.WriteLine(" -reconnect" & ControlChars.Tab & _
"- Drop and re-make the " & _
"connection with the same Session-ID")
If build_mode = axtls.SSL_BUILD_FULL_MODE Then
Console.WriteLine(" -debug" & _
ControlChars.Tab & ControlChars.Tab & _
"- Print more output")
Console.WriteLine(" -state" & _
ControlChars.Tab & ControlChars.Tab & _
"- Show state messages")
Console.WriteLine(" -show-rsa" & ControlChars.Tab & _
"- Show RSA state")
End If
Else
Console.WriteLine("Change configuration to allow this feature")
End If
Environment.Exit(1)
End Sub
End Class
Public Module MyMain
Function Main(ByVal args() As String) As Integer
Dim runner As axssl = New axssl()
If args.Length = 1 And args(0) = "version" Then
Console.WriteLine("axssl.vbnet " & SSLUtil.Version())
Environment.Exit(0)
End If
If args.Length < 1
runner.print_options("")
ElseIf args(0) <> "s_server" And args(0) <> "s_client"
runner.print_options(args(0))
End If
Dim build_mode As Integer = SSLUtil.BuildMode()
If args(0) = "s_server" Then
runner.do_server(build_mode, args)
Else
runner.do_client(build_mode, args)
End If
End Function
End Module

View File

@@ -243,13 +243,16 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
memset(&tm, 0, sizeof(struct tm));
tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
if (tm.tm_year <= 50) /* 1951-2050 thing */
if (tm.tm_year < 50) /* 1951-2050 thing */
{
tm.tm_year += 100;
}
tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
tm.tm_hour = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
tm.tm_min = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
tm.tm_sec = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
*t = mktime(&tm);
*offset += len;
ret = X509_OK;
@@ -274,13 +277,14 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
}
else
{
tm.tm_year = abs_year - 1900;
tm.tm_mon = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0') - 1;
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
*t = mktime(&tm);
tm.tm_year = abs_year - 1900;
tm.tm_mon = (buf[t_offset+4] - '0')*10 +
(buf[t_offset+5] - '0') - 1;
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
*t = mktime(&tm);
}
*offset += len;

View File

@@ -231,7 +231,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
* @return ssl_ext Pointer to SSL_EXTENSIONS structure
*
*/
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new();
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new(void);
/**
* @brief Set the host name for SNI extension
@@ -281,7 +281,8 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
* can be null if no session resumption is being used or required. This option
* is not used in skeleton mode.
* @param sess_id_size The size of the session id (max 32)
* @param ssl_ext pointer to a structure with the activated SSL extensions and their values
* @param ssl_ext pointer to a structure with the activated SSL extensions
* and their values
* @return An SSL object reference. Use ssl_handshake_status() to check
* if a handshake succeeded.
*/
@@ -373,8 +374,8 @@ EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
* @return The cipher id. This will be one of the following:
* - SSL_AES128_SHA (0x2f)
* - SSL_AES256_SHA (0x35)
* - SSL_RC4_128_SHA (0x05)
* - SSL_RC4_128_MD5 (0x04)
* - SSL_AES128_SHA256 (0x3c)
* - SSL_AES256_SHA256 (0x3d)
*/
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);

View File

@@ -1587,7 +1587,7 @@ static int SSL_client_test(
#endif
}
usleep(200000); /* allow server to start */
usleep(500000); /* allow server to start */
if (*ssl_ctx == NULL)
{
@@ -1649,7 +1649,8 @@ static int SSL_client_test(
goto client_test_exit;
}
ssl = ssl_client_new(*ssl_ctx, client_fd, session_id, sizeof(session_id));
ssl = ssl_client_new(*ssl_ctx, client_fd,
session_id, sizeof(session_id), NULL);
/* check the return status */
if ((ret = ssl_handshake_status(ssl)))
@@ -1938,7 +1939,7 @@ static void do_basic(void)
"../ssl/test/axTLS.ca_x509.cer", NULL))
goto error;
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0, NULL);
/* check the return status */
if (ssl_handshake_status(ssl_clnt) < 0)
@@ -2062,7 +2063,7 @@ static void do_unblocked(void)
"../ssl/test/axTLS.ca_x509.cer", NULL))
goto error;
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0, NULL);
while (ssl_handshake_status(ssl_clnt) != SSL_OK)
{
@@ -2182,7 +2183,7 @@ void do_multi_clnt(multi_t *multi_data)
goto client_test_exit;
usleep(200000);
ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0);
ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0, NULL);
if ((res = ssl_handshake_status(ssl)))
{

View File

@@ -158,11 +158,13 @@ EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new()
*/
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext)
{
if(ssl_ext == NULL ) {
if (ssl_ext == NULL )
{
return;
}
if(ssl_ext->host_name != NULL) {
if (ssl_ext->host_name != NULL)
{
free(ssl_ext->host_name);
}
free(ssl_ext);

View File

@@ -173,9 +173,12 @@ typedef struct
uint8_t key_block_generated;
} DISPOSABLE_CTX;
typedef struct {
typedef struct
{
char *host_name; /* Needed for the SNI support */
uint16_t max_fragment_size; /* Needed for the Max Fragment Size Extension. Allowed values: 2^9, 2^10 .. 2^14 */
/* Needed for the Max Fragment Size Extension.
Allowed values: 2^9, 2^10 .. 2^14 */
uint16_t max_fragment_size;
} SSL_EXTENSIONS;
struct _SSL

View File

@@ -195,9 +195,8 @@ static int send_client_hello(SSL *ssl)
time_t tm = time(NULL);
uint8_t *tm_ptr = &buf[6]; /* time will go here */
int i, offset, ext_offset;
uint16_t ext_len; /* extensions total length */
int ext_len = 0;
ext_len = 0;
buf[0] = HS_CLIENT_HELLO;
buf[1] = 0;
@@ -257,39 +256,44 @@ static int send_client_hello(SSL *ssl)
ext_len += sizeof(g_sig_alg);
}
if (ssl->extensions != NULL) {
if (ssl->extensions != NULL)
{
/* send the host name if specified */
if (ssl->extensions->host_name != NULL) {
unsigned int host_len = strlen(ssl->extensions->host_name);
buf[offset++] = 0;
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
buf[offset++] = 0;
buf[offset++] = host_len + 5; /* server_name length */
buf[offset++] = 0;
buf[offset++] = host_len + 3; /* server_list length */
buf[offset++] = 0; /* host_name(0) (255) */
buf[offset++] = 0;
buf[offset++] = host_len; /* host_name length */
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
offset += host_len;
ext_len += host_len + 9;
if (ssl->extensions->host_name != NULL)
{
size_t host_len = strlen(ssl->extensions->host_name);
buf[offset++] = 0;
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
buf[offset++] = 0;
buf[offset++] = host_len + 5; /* server_name length */
buf[offset++] = 0;
buf[offset++] = host_len + 3; /* server_list length */
buf[offset++] = 0; /* host_name(0) (255) */
buf[offset++] = 0;
buf[offset++] = host_len; /* host_name length */
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
offset += host_len;
ext_len += host_len + 9;
}
if (ssl->extensions->max_fragment_size) {
buf[offset++] = 0;
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
if (ssl->extensions->max_fragment_size)
{
buf[offset++] = 0;
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
buf[offset++] = 0; // size of data
buf[offset++] = 2;
buf[offset++] = 0; // size of data
buf[offset++] = 2;
buf[offset++] = (uint8_t)((ssl->extensions->max_fragment_size >> 8) & 0xff);
buf[offset++] = (uint8_t)(ssl->extensions->max_fragment_size & 0xff);
ext_len += 6;
buf[offset++] = (uint8_t)
((ssl->extensions->max_fragment_size >> 8) & 0xff);
buf[offset++] = (uint8_t)
(ssl->extensions->max_fragment_size & 0xff);
ext_len += 6;
}
}
if(ext_len > 0) {
if (ext_len > 0)
{
// update the extensions length value
buf[ext_offset] = (uint8_t) ((ext_len >> 8) & 0xff);
buf[ext_offset + 1] = (uint8_t) (ext_len & 0xff);