From f592df2e1ffa9872f511a7991752492c7c46e615 Mon Sep 17 00:00:00 2001 From: cameronrich Date: Fri, 25 May 2007 06:08:19 +0000 Subject: [PATCH] added lua work git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@100 9a5d90b5-6617-0410-8a86-bb477d3ed2e3 --- samples/Makefile | 4 + samples/lua/Makefile | 31 +++ samples/lua/axssl.lua | 535 ++++++++++++++++++++++++++++++++++++++++++ samples/perl/axssl.pl | 11 +- 4 files changed, 576 insertions(+), 5 deletions(-) create mode 100644 samples/lua/Makefile create mode 100755 samples/lua/axssl.lua diff --git a/samples/Makefile b/samples/Makefile index fbb31149a..fdbdb9970 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -37,6 +37,9 @@ endif ifdef CONFIG_PERL_SAMPLES $(MAKE) -C perl endif +ifdef CONFIG_LUA_SAMPLES + $(MAKE) -C lua +endif clean:: $(MAKE) -C c clean @@ -44,3 +47,4 @@ clean:: $(MAKE) -C vbnet clean $(MAKE) -C java clean $(MAKE) -C perl clean + $(MAKE) -C lua clean diff --git a/samples/lua/Makefile b/samples/lua/Makefile new file mode 100644 index 000000000..3c90813cf --- /dev/null +++ b/samples/lua/Makefile @@ -0,0 +1,31 @@ +# +# Copyright(C) 2007 Cameron Rich +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +include ../../config/.config +include ../../config/makefile.conf + +all: samples +TARGET=../../$(STAGE)/axssl.lua +samples: $(TARGET) + +$(TARGET): axssl.lua + install $< $@ + +clean:: + -@rm -f $(TARGET) + diff --git a/samples/lua/axssl.lua b/samples/lua/axssl.lua new file mode 100755 index 000000000..f1d933586 --- /dev/null +++ b/samples/lua/axssl.lua @@ -0,0 +1,535 @@ +#!/usr/bin/lua +-- +-- +-- Copyright(C) 2006 Cameron Rich +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- + +-- +-- 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. +-- +-- +local f = loadlib("axtlsl.dll", "luaopen_axtlsl") +f() + +-- print version? + +if #arg == 1 and arg[1] == "version" then + print("axssl.lua "..ssl_version().."\n") + 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 + +-- +-- Main entry point. Doesn't do much except works out whether we are a client +-- or a server. +-- +if #arg < 1 or (arg[1] ~= "s_server" and arg[1] ~= "s_client") then + print_options(#arg > 0 and arg[1] or "") +end + +--[[ +local build_mode = ssl_get_config(SSL_BUILD_MODE) +arg[1] eq "s_server" ? do_server(build_mode) : do_client(build_mode) + +-- Implement the SSL server logic. +function do_server(build_mode) + local i = 1 + local port = 4433 + local options = SSL_DISPLAY_CERTS + local quiet = false + local password = nil + local private_key_file = nil + local cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET) + local ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET) + local cert = {} + local ca_cert = {} + + while i <= #arg do + if arg[i] eq "-accept" then + if i >= #arg then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + port = arg[i] + elseif arg[i] eq "-quiet" then + quiet = true + options = options & ~SSL_DISPLAY_CERTS + elseif build_mode >= SSL_BUILD_SERVER_ONLY then + if arg[i] eq "-cert" then + if i >= #arg >= cert_size-1 then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + cert[i] = arg[i] + elseif arg[i] eq "-key" then + if i >= #arg then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + private_key_file = arg[i] + options = options | SSL_NO_DEFAULT_KEY + elseif arg[i] eq "-pass" then + if i >= #arg then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + password = arg[i] + elseif build_mode >= SSL_BUILD_ENABLE_VERIFICATION then + if arg[i] eq "-verify" then + options = options | SSL_CLIENT_AUTHENTICATION + elseif arg[i] eq "-CAfile" then + if i >= #arg >= ca_cert_size-1 then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + ca_cert[i] = arg[i] + elseif build_mode == SSL_BUILD_FULL_MODE then + if arg[i] eq "-debug" then + options = options | SSL_DISPLAY_BYTES + elseif arg[i] eq "-state" then + options = options | SSL_DISPLAY_STATES + elseif arg[i] eq "-show-rsa" then + options = options | 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 = 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. + --------------------------------------------------------------------------- + local ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS) + if ssl_ctx == nil then error("Error: Server context is invalid") end + + if nil private_key_file then + local obj_type = SSL_OBJ_RSA_KEY + + if private_key_file =~ /.p8/ then obj_type = SSL_OBJ_PKCS8 end + if private_key_file =~ /.p12/ then obj_type = SSL_OBJ_PKCS12 end + + if ssl_obj_load(ssl_ctx, obj_type, private_key_file, password) then + error("Private key 'private_key_file' is nilined.") + end + end + + foreach (@cert) + if ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, _, nil) #arg= SSL_OK then + error("Certificate '_' is undefined.") + end + end + + foreach (@ca_cert) + if ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, _, nil) #arg= SSL_OK then + error("Certificate '_' is undefined.") + end + end + + while true do + if not quiet then print("ACCEPT\n") end + local client_sock = server_sock->accept + local native_sock = get_native_sock(client_sock->fileno) + + -- This doesn't work in Win32 - need to get file descriptor from socket. + local ssl = ssl_server_new(ssl_ctx, native_sock) + + -- do the actual SSL handshake + local res + local buf + + while true do + (res, buf) = ssl_read(ssl, nil) + if res #arg= SSL_OK then break end + + -- check when the connection has been established + if ssl_handshake_status(ssl) == SSL_OK then break end + + -- could do something else here + end + + if res == SSL_OK then -- connection established and ok + if not quiet then + display_session_id(ssl) + display_cipher(ssl) + end + + -- now read (and display) whatever the client sends us + while true do + -- keep reading until we get something interesting + while true do + (res, buf) = ssl_read(ssl, nil) + if res #arg= SSL_OK then break end + + -- could do something else here + end + + if res < SSL_OK then + if not quiet then print("CONNECTION CLOSED\n") end + break + end + + print(buf) + end + elseif not quiet then + ssl_display_error(res) + end + + -- client was disconnected or the handshake failed. + ssl_free(ssl) + client_sock->close + end + + ssl_ctx_free(ssl_ctx) +end + +-- +-- Implement the SSL client logic. +-- +function do_client(build_mode) + local i = 1 + local port = 4433 + local options = SSL_SERVER_VERIFY_LATER|SSL_DISPLAY_CERTS + local private_key_file = nil + local reconnect = 0 + local quiet = false + local password = nil + local session_id = {} + local host = "127.0.0.1" + local @cert + local @ca_cert + local cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET) + local ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET) + + while i <= #arg do + if arg[i] eq "-connect" then + if i >= #arg then + print_client_options(build_mode, arg[i]) + end + + i = i + 1 + (host, port) = split(':', arg[i]) + elseif arg[i] eq "-cert" then + if i >= #arg >= cert_size-1 then + print_client_options(build_mode, arg[i]) + end + + i = i + 1 + cert[i] = arg[i] + elseif arg[i] eq "-key" then + if i >= #arg then + print_client_options(build_mode, arg[i]) + end + + i = i + 1 + private_key_file = arg[i] + options |= SSL_NO_DEFAULT_KEY + elseif arg[i] eq "-CAfile" then + if i >= #arg >= ca_cert_size-1 then + print_client_options(build_mode, arg[i]) + end + + i = i + 1 + ca_cert[i] = arg[i] + elseif arg[i] eq "-verify" then + options &= ~SSL_SERVER_VERIFY_LATER + elseif arg[i] eq "-reconnect" then + reconnect = 4 + elseif arg[i] eq "-quiet" then + quiet = true + options &= ~SSL_DISPLAY_CERTS + elseif arg[i] eq "-pass" then + if i >= #arg then + print_server_options(build_mode, arg[i]) + end + + i = i + 1 + password = arg[i] + elseif build_mode == SSL_BUILD_FULL_MODE then + if arg[i] eq "-debug" then + options = options | SSL_DISPLAY_BYTES + elseif arg[i] eq "-state" then + options = options | SSL_DISPLAY_STATES + elseif arg[i] eq "-show-rsa" then + options = options | 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 = new IO::Socket::INET ( + PeerAddr => host, PeerPort => port, Proto => 'tcp') + or error("no socket: !") + local ssl + local res + local native_sock = get_native_sock(client_sock->fileno) + + if not quiet then print("CONNECTED\n") 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 = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS) + + if ssl_ctx == nil then + error("Error: Client context is invalid") + end + + if private_key_file not nil then + local obj_type = SSL_OBJ_RSA_KEY + + if private_key_file =~ /.p8/ then + obj_type = SSL_OBJ_PKCS8 + end + if private_key_file =~ /.p12/ then + obj_type = SSL_OBJ_PKCS12 + end + + if ssl_obj_load(ssl_ctx, obj_type, private_key_file, password) then + error("Private key 'private_key_file' is undefined.") + end + end + + foreach (@cert) + if ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, _, nil) then + error("Certificate '_' is undefined.") + end + end + + foreach (@ca_cert) + if ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, _, nil) then + error("Certificate '_' is undefined.") + end + end + + -- Try session resumption? + if reconnect then + local session_id = nil + while reconnect do + reconnect = reconnect - 1 + ssl = ssl_client_new(ssl_ctx, native_sock, session_id) + + res = ssl_handshake_status(ssl) + if res #arg= SSL_OK then + if not quiet then ssl_display_error(res) end + ssl_free(ssl) + os.exit(1) + end + + display_session_id(ssl) + session_id = ssl_get_session_id(ssl) + + if reconnect then + ssl_free(ssl) + client_sock->close + client_sock = new IO::Socket::INET ( + PeerAddr => host, PeerPort => port, Proto => 'tcp') + or error ("no socket: !") + + end + end + else + ssl = ssl_client_new(ssl_ctx, native_sock, nil) + end + + -- check the return status + res = ssl_handshake_status(ssl) + if res #arg= SSL_OK then + if not quiet then ssl_display_error(res) end + os.exit(1) + end + + if not quiet then + local common_name = ssl_get_cert_dn(ssl, + SSL_X509_CERT_COMMON_NAME) + + if common_name not nil then + print("Common Name:\t\t%s\n", common_name) + end + + display_session_id(ssl) + display_cipher(ssl) + end + + while do + local cstring = pack("a*x", _); -- add null terminator + res = ssl_write(ssl, \cstring, length(cstring)) + if res < SSL_OK then + if not quiet then ssl_display_error(res) end + break + end + end + + ssl_ctx_free(ssl_ctx) + client_sock->close +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 = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET) + local ca_cert_size = ssl_get_config( + SSL_MAX_CA_CERT_CFG_OFFSET) + + print("unknown option "..option.."") + print("usage: s_server [args ...]") + print(" -accept\t\t- port to accept on (default is 4433)") + print(" -quiet\t\t- No server output\n") + + if build_mode >= SSL_BUILD_SERVER_ONLY then + print(" -cert arg\t- certificate file to add (in addition to default then". + " to chain -". + "\t\t default DER format. Can repeat up to %d times\n", cert_size) + 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 >= 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 %d times\n", ca_cert_size) + end + + if build_mode == 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 = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET) + local ca_cert_size = ssl_get_config( + SSL_MAX_CA_CERT_CFG_OFFSET) + + print("unknown option %s\n", option) + + if build_mode >= 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 %d times\n", cert_size) + print(" -CAfile arg\t- Certificate authority - default DER format") + print("\t\t Can repeat up to %d times\n", ca_cert_size) + 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 == 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\n") + end + else + print("Change configuration to allow this feature") + end + + os.exit(1) +end + +-- +-- Display what cipher we are using +-- +function display_cipher(ss) + local (ssl) = @_ + print("CIPHER is ") + local cipher_id = ssl_get_cipher_id(ssl) + + if cipher_id == SSL_AES128_SHA then + print("AES128-SHA") + elseif cipher_id == SSL_AES256_SHA then + print("AES256-SHA") + elseif SSL_RC4_128_SHA then + print("RC4-SHA") + elseif SSL_RC4_128_MD5 then + print("RC4-MD5") + else + print("Unknown - %d", cipher_id) + end + + print("\n") +end + +-- +-- Display what session id we have. +-- +function display_session_id(ss) + local session_id = ssl_get_session_id(ssl) + + print("-----BEGIN SSL SESSION PARAMETERS-----\n") + print(unpack("H*", session_id)) + print("\n-----END SSL SESSION PARAMETERS-----\n") +end +--]] + diff --git a/samples/perl/axssl.pl b/samples/perl/axssl.pl index cbfd58fdb..cf04254dd 100755 --- a/samples/perl/axssl.pl +++ b/samples/perl/axssl.pl @@ -58,16 +58,17 @@ sub get_native_sock return $is_win32 ? FdGetOsFHandle($sock) : $sock; } -# -# Main entry point. Doesn't do much except works out whether we are a client -# or a server. -# +# 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")); @@ -494,7 +495,7 @@ sub print_options { my ($option) = @_; printf("axssl: Error: '%s' is an invalid command.\n", $option); - printf("usage: axssl [s_server|s_client] [args ...]\n"); + printf("usage: axssl [s_server|s_client|version] [args ...]\n"); exit 1; }