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));
|
||||
tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
|
||||
|
||||
if (tm.tm_year <= 50) /* 1951-2050 thing */
|
||||
if (tm.tm_year < 50) /* 1951-2050 thing */
|
||||
{
|
||||
tm.tm_year += 100;
|
||||
}
|
||||
|
||||
tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
|
||||
tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
|
||||
tm.tm_hour = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
|
||||
tm.tm_min = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
|
||||
tm.tm_sec = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
|
||||
*t = mktime(&tm);
|
||||
*offset += len;
|
||||
ret = X509_OK;
|
||||
@@ -274,13 +277,14 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
|
||||
}
|
||||
else
|
||||
{
|
||||
tm.tm_year = abs_year - 1900;
|
||||
tm.tm_mon = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0') - 1;
|
||||
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
|
||||
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
|
||||
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
|
||||
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
|
||||
*t = mktime(&tm);
|
||||
tm.tm_year = abs_year - 1900;
|
||||
tm.tm_mon = (buf[t_offset+4] - '0')*10 +
|
||||
(buf[t_offset+5] - '0') - 1;
|
||||
tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
|
||||
tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
|
||||
tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
|
||||
tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
|
||||
*t = mktime(&tm);
|
||||
}
|
||||
|
||||
*offset += len;
|
||||
|
@@ -231,7 +231,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
|
||||
* @return ssl_ext Pointer to SSL_EXTENSIONS structure
|
||||
*
|
||||
*/
|
||||
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new();
|
||||
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new(void);
|
||||
|
||||
/**
|
||||
* @brief Set the host name for SNI extension
|
||||
@@ -281,7 +281,8 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
|
||||
* can be null if no session resumption is being used or required. This option
|
||||
* is not used in skeleton mode.
|
||||
* @param sess_id_size The size of the session id (max 32)
|
||||
* @param ssl_ext pointer to a structure with the activated SSL extensions and their values
|
||||
* @param ssl_ext pointer to a structure with the activated SSL extensions
|
||||
* and their values
|
||||
* @return An SSL object reference. Use ssl_handshake_status() to check
|
||||
* if a handshake succeeded.
|
||||
*/
|
||||
@@ -373,8 +374,8 @@ EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
|
||||
* @return The cipher id. This will be one of the following:
|
||||
* - SSL_AES128_SHA (0x2f)
|
||||
* - SSL_AES256_SHA (0x35)
|
||||
* - SSL_RC4_128_SHA (0x05)
|
||||
* - SSL_RC4_128_MD5 (0x04)
|
||||
* - SSL_AES128_SHA256 (0x3c)
|
||||
* - SSL_AES256_SHA256 (0x3d)
|
||||
*/
|
||||
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
|
||||
|
||||
|
@@ -1587,7 +1587,7 @@ static int SSL_client_test(
|
||||
#endif
|
||||
}
|
||||
|
||||
usleep(200000); /* allow server to start */
|
||||
usleep(500000); /* allow server to start */
|
||||
|
||||
if (*ssl_ctx == NULL)
|
||||
{
|
||||
@@ -1649,7 +1649,8 @@ static int SSL_client_test(
|
||||
goto client_test_exit;
|
||||
}
|
||||
|
||||
ssl = ssl_client_new(*ssl_ctx, client_fd, session_id, sizeof(session_id));
|
||||
ssl = ssl_client_new(*ssl_ctx, client_fd,
|
||||
session_id, sizeof(session_id), NULL);
|
||||
|
||||
/* check the return status */
|
||||
if ((ret = ssl_handshake_status(ssl)))
|
||||
@@ -1938,7 +1939,7 @@ static void do_basic(void)
|
||||
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
||||
goto error;
|
||||
|
||||
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
|
||||
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0, NULL);
|
||||
|
||||
/* check the return status */
|
||||
if (ssl_handshake_status(ssl_clnt) < 0)
|
||||
@@ -2062,7 +2063,7 @@ static void do_unblocked(void)
|
||||
"../ssl/test/axTLS.ca_x509.cer", NULL))
|
||||
goto error;
|
||||
|
||||
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
|
||||
ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0, NULL);
|
||||
|
||||
while (ssl_handshake_status(ssl_clnt) != SSL_OK)
|
||||
{
|
||||
@@ -2182,7 +2183,7 @@ void do_multi_clnt(multi_t *multi_data)
|
||||
goto client_test_exit;
|
||||
|
||||
usleep(200000);
|
||||
ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0);
|
||||
ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0, NULL);
|
||||
|
||||
if ((res = ssl_handshake_status(ssl)))
|
||||
{
|
||||
|
@@ -158,11 +158,13 @@ EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new()
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext)
|
||||
{
|
||||
if(ssl_ext == NULL ) {
|
||||
if (ssl_ext == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(ssl_ext->host_name != NULL) {
|
||||
if (ssl_ext->host_name != NULL)
|
||||
{
|
||||
free(ssl_ext->host_name);
|
||||
}
|
||||
free(ssl_ext);
|
||||
|
@@ -173,9 +173,12 @@ typedef struct
|
||||
uint8_t key_block_generated;
|
||||
} DISPOSABLE_CTX;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
char *host_name; /* Needed for the SNI support */
|
||||
uint16_t max_fragment_size; /* Needed for the Max Fragment Size Extension. Allowed values: 2^9, 2^10 .. 2^14 */
|
||||
/* Needed for the Max Fragment Size Extension.
|
||||
Allowed values: 2^9, 2^10 .. 2^14 */
|
||||
uint16_t max_fragment_size;
|
||||
} SSL_EXTENSIONS;
|
||||
|
||||
struct _SSL
|
||||
|
@@ -195,9 +195,8 @@ static int send_client_hello(SSL *ssl)
|
||||
time_t tm = time(NULL);
|
||||
uint8_t *tm_ptr = &buf[6]; /* time will go here */
|
||||
int i, offset, ext_offset;
|
||||
uint16_t ext_len; /* extensions total length */
|
||||
int ext_len = 0;
|
||||
|
||||
ext_len = 0;
|
||||
|
||||
buf[0] = HS_CLIENT_HELLO;
|
||||
buf[1] = 0;
|
||||
@@ -257,39 +256,44 @@ static int send_client_hello(SSL *ssl)
|
||||
ext_len += sizeof(g_sig_alg);
|
||||
}
|
||||
|
||||
if (ssl->extensions != NULL) {
|
||||
if (ssl->extensions != NULL)
|
||||
{
|
||||
/* send the host name if specified */
|
||||
if (ssl->extensions->host_name != NULL) {
|
||||
unsigned int host_len = strlen(ssl->extensions->host_name);
|
||||
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len + 5; /* server_name length */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len + 3; /* server_list length */
|
||||
buf[offset++] = 0; /* host_name(0) (255) */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len; /* host_name length */
|
||||
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
|
||||
offset += host_len;
|
||||
ext_len += host_len + 9;
|
||||
if (ssl->extensions->host_name != NULL)
|
||||
{
|
||||
size_t host_len = strlen(ssl->extensions->host_name);
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len + 5; /* server_name length */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len + 3; /* server_list length */
|
||||
buf[offset++] = 0; /* host_name(0) (255) */
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = host_len; /* host_name length */
|
||||
strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
|
||||
offset += host_len;
|
||||
ext_len += host_len + 9;
|
||||
}
|
||||
|
||||
if (ssl->extensions->max_fragment_size) {
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
|
||||
if (ssl->extensions->max_fragment_size)
|
||||
{
|
||||
buf[offset++] = 0;
|
||||
buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
|
||||
|
||||
buf[offset++] = 0; // size of data
|
||||
buf[offset++] = 2;
|
||||
buf[offset++] = 0; // size of data
|
||||
buf[offset++] = 2;
|
||||
|
||||
buf[offset++] = (uint8_t)((ssl->extensions->max_fragment_size >> 8) & 0xff);
|
||||
buf[offset++] = (uint8_t)(ssl->extensions->max_fragment_size & 0xff);
|
||||
ext_len += 6;
|
||||
buf[offset++] = (uint8_t)
|
||||
((ssl->extensions->max_fragment_size >> 8) & 0xff);
|
||||
buf[offset++] = (uint8_t)
|
||||
(ssl->extensions->max_fragment_size & 0xff);
|
||||
ext_len += 6;
|
||||
}
|
||||
}
|
||||
|
||||
if(ext_len > 0) {
|
||||
if (ext_len > 0)
|
||||
{
|
||||
// update the extensions length value
|
||||
buf[ext_offset] = (uint8_t) ((ext_len >> 8) & 0xff);
|
||||
buf[ext_offset + 1] = (uint8_t) (ext_len & 0xff);
|
||||
|
Reference in New Issue
Block a user