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:
committed by
Ivan Grokhotkov
parent
a68324f17c
commit
425067abe6
105
bindings/Config.in
Normal file
105
bindings/Config.in
Normal 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
491
bindings/csharp/axTLS.cs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** @} */
|
392
bindings/generate_SWIG_interface.pl
Executable file
392
bindings/generate_SWIG_interface.pl
Executable 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
137
bindings/java/SSL.java
Normal 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
134
config/makefile.conf
Normal 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
912
samples/c/axssl.c
Normal 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
758
samples/csharp/axssl.cs
Normal 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
51
samples/java/Makefile
Normal 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
760
samples/java/axssl.java
Normal 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
562
samples/lua/axssl.lua
Executable 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
634
samples/perl/axssl.pl
Executable 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
702
samples/vbnet/axssl.vb
Normal 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
|
20
ssl/asn1.c
20
ssl/asn1.c
@@ -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));
|
memset(&tm, 0, sizeof(struct tm));
|
||||||
tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
|
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_year += 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
|
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_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);
|
*t = mktime(&tm);
|
||||||
*offset += len;
|
*offset += len;
|
||||||
ret = X509_OK;
|
ret = X509_OK;
|
||||||
@@ -274,13 +277,14 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.tm_year = abs_year - 1900;
|
tm.tm_year = abs_year - 1900;
|
||||||
tm.tm_mon = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0') - 1;
|
tm.tm_mon = (buf[t_offset+4] - '0')*10 +
|
||||||
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
|
(buf[t_offset+5] - '0') - 1;
|
||||||
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
|
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
|
||||||
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
|
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
|
||||||
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
|
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
|
||||||
*t = mktime(&tm);
|
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
|
||||||
|
*t = mktime(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
*offset += len;
|
*offset += len;
|
||||||
|
@@ -231,7 +231,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
|
|||||||
* @return ssl_ext Pointer to SSL_EXTENSIONS structure
|
* @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
|
* @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
|
* can be null if no session resumption is being used or required. This option
|
||||||
* is not used in skeleton mode.
|
* is not used in skeleton mode.
|
||||||
* @param sess_id_size The size of the session id (max 32)
|
* @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
|
* @return An SSL object reference. Use ssl_handshake_status() to check
|
||||||
* if a handshake succeeded.
|
* 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:
|
* @return The cipher id. This will be one of the following:
|
||||||
* - SSL_AES128_SHA (0x2f)
|
* - SSL_AES128_SHA (0x2f)
|
||||||
* - SSL_AES256_SHA (0x35)
|
* - SSL_AES256_SHA (0x35)
|
||||||
* - SSL_RC4_128_SHA (0x05)
|
* - SSL_AES128_SHA256 (0x3c)
|
||||||
* - SSL_RC4_128_MD5 (0x04)
|
* - SSL_AES256_SHA256 (0x3d)
|
||||||
*/
|
*/
|
||||||
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
|
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
|
||||||
|
|
||||||
|
@@ -1587,7 +1587,7 @@ static int SSL_client_test(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(200000); /* allow server to start */
|
usleep(500000); /* allow server to start */
|
||||||
|
|
||||||
if (*ssl_ctx == NULL)
|
if (*ssl_ctx == NULL)
|
||||||
{
|
{
|
||||||
@@ -1649,7 +1649,8 @@ static int SSL_client_test(
|
|||||||
goto client_test_exit;
|
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 */
|
/* check the return status */
|
||||||
if ((ret = ssl_handshake_status(ssl)))
|
if ((ret = ssl_handshake_status(ssl)))
|
||||||
@@ -1938,7 +1939,7 @@ static void do_basic(void)
|
|||||||
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
||||||
goto error;
|
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 */
|
/* check the return status */
|
||||||
if (ssl_handshake_status(ssl_clnt) < 0)
|
if (ssl_handshake_status(ssl_clnt) < 0)
|
||||||
@@ -2062,7 +2063,7 @@ static void do_unblocked(void)
|
|||||||
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
||||||
goto error;
|
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)
|
while (ssl_handshake_status(ssl_clnt) != SSL_OK)
|
||||||
{
|
{
|
||||||
@@ -2182,7 +2183,7 @@ void do_multi_clnt(multi_t *multi_data)
|
|||||||
goto client_test_exit;
|
goto client_test_exit;
|
||||||
|
|
||||||
usleep(200000);
|
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)))
|
if ((res = ssl_handshake_status(ssl)))
|
||||||
{
|
{
|
||||||
|
@@ -158,11 +158,13 @@ EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new()
|
|||||||
*/
|
*/
|
||||||
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext)
|
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext)
|
||||||
{
|
{
|
||||||
if(ssl_ext == NULL ) {
|
if (ssl_ext == NULL )
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ssl_ext->host_name != NULL) {
|
if (ssl_ext->host_name != NULL)
|
||||||
|
{
|
||||||
free(ssl_ext->host_name);
|
free(ssl_ext->host_name);
|
||||||
}
|
}
|
||||||
free(ssl_ext);
|
free(ssl_ext);
|
||||||
|
@@ -173,9 +173,12 @@ typedef struct
|
|||||||
uint8_t key_block_generated;
|
uint8_t key_block_generated;
|
||||||
} DISPOSABLE_CTX;
|
} DISPOSABLE_CTX;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
char *host_name; /* Needed for the SNI support */
|
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;
|
} SSL_EXTENSIONS;
|
||||||
|
|
||||||
struct _SSL
|
struct _SSL
|
||||||
|
@@ -195,9 +195,8 @@ static int send_client_hello(SSL *ssl)
|
|||||||
time_t tm = time(NULL);
|
time_t tm = time(NULL);
|
||||||
uint8_t *tm_ptr = &buf[6]; /* time will go here */
|
uint8_t *tm_ptr = &buf[6]; /* time will go here */
|
||||||
int i, offset, ext_offset;
|
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[0] = HS_CLIENT_HELLO;
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
@@ -257,39 +256,44 @@ static int send_client_hello(SSL *ssl)
|
|||||||
ext_len += sizeof(g_sig_alg);
|
ext_len += sizeof(g_sig_alg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl->extensions != NULL) {
|
if (ssl->extensions != NULL)
|
||||||
|
{
|
||||||
/* send the host name if specified */
|
/* send the host name if specified */
|
||||||
if (ssl->extensions->host_name != NULL) {
|
if (ssl->extensions->host_name != NULL)
|
||||||
unsigned int host_len = strlen(ssl->extensions->host_name);
|
{
|
||||||
|
size_t host_len = strlen(ssl->extensions->host_name);
|
||||||
buf[offset++] = 0;
|
buf[offset++] = 0;
|
||||||
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
|
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
|
||||||
buf[offset++] = 0;
|
buf[offset++] = 0;
|
||||||
buf[offset++] = host_len + 5; /* server_name length */
|
buf[offset++] = host_len + 5; /* server_name length */
|
||||||
buf[offset++] = 0;
|
buf[offset++] = 0;
|
||||||
buf[offset++] = host_len + 3; /* server_list length */
|
buf[offset++] = host_len + 3; /* server_list length */
|
||||||
buf[offset++] = 0; /* host_name(0) (255) */
|
buf[offset++] = 0; /* host_name(0) (255) */
|
||||||
buf[offset++] = 0;
|
buf[offset++] = 0;
|
||||||
buf[offset++] = host_len; /* host_name length */
|
buf[offset++] = host_len; /* host_name length */
|
||||||
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
|
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
|
||||||
offset += host_len;
|
offset += host_len;
|
||||||
ext_len += host_len + 9;
|
ext_len += host_len + 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl->extensions->max_fragment_size) {
|
if (ssl->extensions->max_fragment_size)
|
||||||
buf[offset++] = 0;
|
{
|
||||||
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
|
buf[offset++] = 0;
|
||||||
|
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
|
||||||
|
|
||||||
buf[offset++] = 0; // size of data
|
buf[offset++] = 0; // size of data
|
||||||
buf[offset++] = 2;
|
buf[offset++] = 2;
|
||||||
|
|
||||||
buf[offset++] = (uint8_t)((ssl->extensions->max_fragment_size >> 8) & 0xff);
|
buf[offset++] = (uint8_t)
|
||||||
buf[offset++] = (uint8_t)(ssl->extensions->max_fragment_size & 0xff);
|
((ssl->extensions->max_fragment_size >> 8) & 0xff);
|
||||||
ext_len += 6;
|
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
|
// update the extensions length value
|
||||||
buf[ext_offset] = (uint8_t) ((ext_len >> 8) & 0xff);
|
buf[ext_offset] = (uint8_t) ((ext_len >> 8) & 0xff);
|
||||||
buf[ext_offset + 1] = (uint8_t) (ext_len & 0xff);
|
buf[ext_offset + 1] = (uint8_t) (ext_len & 0xff);
|
||||||
|
Reference in New Issue
Block a user