1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

new trunk

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@78 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2007-03-14 12:03:51 +00:00
parent 974cf12924
commit 73dfbb7568
177 changed files with 46362 additions and 0 deletions

162
Makefile Normal file
View File

@ -0,0 +1,162 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This license is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This license 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 Lesser General Public License
# along with this license; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-include config/.config
ifneq ($(strip $(HAVE_DOT_CONFIG)),y)
all: menuconfig
else
all: target
endif
include config/makefile.conf
target : $(STAGE) $(TARGET)
# VERSION has to come from the command line
RELEASE=axTLS-$(VERSION)
# standard version
target:
$(MAKE) -C ssl
ifdef CONFIG_AXHTTPD
$(MAKE) -C httpd
endif
ifdef CONFIG_BINDINGS
$(MAKE) -C bindings
endif
ifdef CONFIG_SAMPLES
$(MAKE) -C samples
endif
$(STAGE) : ssl/version.h
@mkdir -p $(STAGE)
# create a version file with something in it.
ssl/version.h:
@echo "#define AXTLS_VERSION \"(no version)\"" > ssl/version.h
$(PREFIX) :
@mkdir -p $(PREFIX)/lib
@mkdir -p $(PREFIX)/bin
release:
$(MAKE) -C config/scripts/config clean
-$(MAKE) clean
-@rm config/*.msi config/*.back.aip config/config.h config/.config*
@rm -fr $(STAGE)
@echo "#define AXTLS_VERSION \"$(VERSION)\"" > ssl/version.h
cd ../; tar cvfz $(RELEASE).tar.gz --wildcards-match-slash --exclude .svn axTLS; cd -;
docs:
$(MAKE) -C docsrc doco
# build the Win32 demo release version
win32_demo:
$(MAKE) win32releaseconf
install: $(PREFIX) all
cp --no-dereference $(STAGE)/libax* $(PREFIX)/lib
chmod 755 $(PREFIX)/lib/libax*
install -m 755 $(STAGE)/ax* $(PREFIX)/bin
ifdef CONFIG_HTTP_HAS_AUTHORIZATION
install -m 755 $(STAGE)/htpasswd $(PREFIX)/bin
endif
ifdef CONFIG_PLATFORM_CYGWIN
install -m 755 $(STAGE)/cygaxtls.dll $(PREFIX)/bin
endif
ifdef CONFIG_PERL_BINDINGS
install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'`
endif
@mkdir -p -m 755 $(PREFIX)/include/axTLS
install -m 644 ssl/*.h $(PREFIX)/include/axTLS
-rm $(PREFIX)/include/axTLS/cert.h
-rm $(PREFIX)/include/axTLS/private_key.h
install -m 644 config/config.h $(PREFIX)/include/axTLS
installclean:
-@rm $(PREFIX)/lib/libax* > /dev/null 2>&1
-@rm $(PREFIX)/bin/ax* > /dev/null 2>&1
-@rm $(PREFIX)/bin/axhttpd* > /dev/null 2>&1
-@rm `perl -e 'use Config; print $$Config{installarchlib};'`/axtlsp.pm > /dev/null 2>&1
test:
cd $(STAGE); ssltest; ../ssl/test/test_axssl.sh; cd -;
# tidy up things
clean::
@cd ssl; $(MAKE) clean
@cd httpd; $(MAKE) clean
@cd samples; $(MAKE) clean
@cd docsrc; $(MAKE) clean
@cd bindings; $(MAKE) clean
# ---------------------------------------------------------------------------
# mconf stuff
# ---------------------------------------------------------------------------
CONFIG_CONFIG_IN = config/Config.in
CONFIG_DEFCONFIG = config/defconfig
config/scripts/config/conf: config/scripts/config/Makefile
$(MAKE) -C config/scripts/config conf
-@if [ ! -f config/.config ] ; then \
cp $(CONFIG_DEFCONFIG) config/.config; \
fi
config/scripts/config/mconf: config/scripts/config/Makefile
$(MAKE) -C config/scripts/config ncurses conf mconf
-@if [ ! -f config/.config ] ; then \
cp $(CONFIG_DEFCONFIG) .config; \
fi
cleanconf:
$(MAKE) -C config/scripts/config clean
@rm -f config/.config
menuconfig: config/scripts/config/mconf
@./config/scripts/config/mconf $(CONFIG_CONFIG_IN)
config: config/scripts/config/conf
@./config/scripts/config/conf $(CONFIG_CONFIG_IN)
oldconfig: config/scripts/config/conf
@./config/scripts/config/conf -o $(CONFIG_CONFIG_IN)
default: config/scripts/config/conf
@./config/scripts/config/conf -d $(CONFIG_CONFIG_IN) > /dev/null
$(MAKE)
randconfig: config/scripts/config/conf
@./config/scripts/config/conf -r $(CONFIG_CONFIG_IN)
allnoconfig: config/scripts/config/conf
@./config/scripts/config/conf -n $(CONFIG_CONFIG_IN)
allyesconfig: config/scripts/config/conf
@./config/scripts/config/conf -y $(CONFIG_CONFIG_IN)
# The special win32 release configuration
win32releaseconf: config/scripts/config/conf
@./config/scripts/config/conf -D config/win32config $(CONFIG_CONFIG_IN) > /dev/null
$(MAKE)
# The special linux release configuration
linuxconf: config/scripts/config/conf
@./config/scripts/config/conf -D config/linuxconfig $(CONFIG_CONFIG_IN) > /dev/null
$(MAKE)

3
README Normal file
View File

@ -0,0 +1,3 @@
See www/index.html for the README, CHANGELOG, LICENSE and other notes.

89
bindings/Config.in Normal file
View File

@ -0,0 +1,89 @@
#
# 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/local/jdk142" 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
endmenu

63
bindings/Makefile Normal file
View File

@ -0,0 +1,63 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
all:
include ../config/.config
include ../config/makefile.conf
ifdef CONFIG_CSHARP_BINDINGS
all: csharp/axInterface.cs
endif
ifdef CONFIG_VBNET_BINDINGS
all: vbnet/axInterface.vb
endif
ifdef CONFIG_JAVA_BINDINGS
all: java/axtlsj.java
endif
ifdef CONFIG_PERL_BINDINGS
all: perl/axTLSp_wrap.c
endif
csharp/axInterface.cs: ../ssl/ssl.h
@perl ./generate_interface.pl -csharp
vbnet/axInterface.vb: ../ssl/ssl.h
@perl ./generate_interface.pl -vbnet
java/axTLSj.i: ../ssl/ssl.h
@perl ./generate_SWIG_interface.pl -java
java/axtlsj.java: java/axTLSj.i $(wildcard java/SSL*.java)
@cd java; swig -java -package axTLSj axTLSj.i; $(MAKE)
perl/axTLSp.i: ../ssl/ssl.h
@perl ./generate_SWIG_interface.pl -perl
perl/axTLSp_wrap.c: perl/axTLSp.i
@cd perl; swig -perl5 axTLSp.i; $(MAKE)
clean::
$(MAKE) -C csharp clean
$(MAKE) -C vbnet clean
$(MAKE) -C java clean
$(MAKE) -C perl clean

43
bindings/README Normal file
View File

@ -0,0 +1,43 @@
===============================================================================
= Language Bindings =
===============================================================================
The tools to generate the various language bindings are done here.
SWIG 1.3.24 or better is required for creating the Java and Perl bindings.
Perl scripts are used to parse ssl.h and automagically give the appropriate
bindings.
At present, the four languages supported are:
* C#
* VB.NET
* Java
* Perl
To generate each binding run the following:
C#:
> generate_interface.pl -csharp
VB.NET:
> generate_interface.pl -vbnet
Java:
> generate_SWIG_interface.pl -java
> cd java; swig -java -package axTLSj -noextern axTLSj.i
Perl:
> generate_SWIG_interface.pl -perl
> cd perl; swig -noextern -perl axTLSp.i
Java and Perl both create a library each called libaxtlsj.so and libaxtlsp.so
(or axtlsj.dll and atlsp.dll on Win32 platforms).
Note: the "-noextern" is deprecated in swig 1.3.27 and newer. The "-noextern"
option was required to get Win32 bindings to work (which is why is has probably
been deprecated).
Each binding (except for Perl) has an extra helper interface to make life
easier.

23
bindings/csharp/Makefile Normal file
View File

@ -0,0 +1,23 @@
#
# 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 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
clean::
@rm -f axssl* axInterface.cs

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

@ -0,0 +1,477 @@
/*
* 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
*/
/**
* 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_RC4_128_SHA (0x05)
* - SSL_RC4_128_MD5 (0x04)
*/
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()
{
byte[] result = new byte[axtls.SSL_SESSION_ID_SIZE];
IntPtr ptr = axtls.ssl_get_session_id(m_ssl);
Marshal.Copy(ptr, result, 0, axtls.SSL_SESSION_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_NO_DEFAULT_KEY: Don't use the default key/certificate. The
* user will load the key/certificate explicitly.
* - 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();
return new SSL(axtls. ssl_client_new(m_ctx, client_fd, session_id));
}
}
}
/** @} */

View File

@ -0,0 +1,328 @@
#!/usr/bin/perl
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#===============================================================
# 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;
}
else
{
$line =~ s/const uint8_t \*(\w+)/const unsigned char $1\[\]/g;
$line =~ s/uint8_t/unsigned char/g;
}
}
return $line;
}
# Parse input file
sub parseFile
{
foreach $line (@_)
{
# 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])
{
goto ouch;
}
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";
}
else
{
ouch:
die "Usage: $0 [-java | -perl]\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 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_SESSION_ID_SIZE);\"
/* 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);
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((const char *)\$1, SSL_SESSION_ID_SIZE);
\$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++;
}
}
%typemap(freearg) unsigned char *in_data {
free(buf\$argnum);
}
/* 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
END
# Initialise loop variables
$skip = 1;
$splitLine = 0;
parseFile(@raw_data);
close(DATA_IN);
close(DATA_OUT);
#===============================================================

307
bindings/generate_interface.pl Executable file
View File

@ -0,0 +1,307 @@
#!/usr/bin/perl -w
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#===============================================================
# This application transforms ssl.h into interfaces that can be used by
# other language bindings. It is "SWIG"-like in nature in that various
# files are generated based on the axTLS API.
#
# The file produced is axInterface.? (depending on the file extension).
#
#===============================================================
use strict;
my $CSHARP = 0;
my $VBNET = 1;
my $binding;
my $skip = 0;
my $signature_ret_type;
# Transforms function signature into an Interface format
sub transformSignature
{
my $item;
my ($line) = @_;
foreach $item ($line)
{
# our very basic preprocessor
if ($binding == $CSHARP)
{
$line =~ s/STDCALL //;
$line =~ s/EXP_FUNC/ [DllImport ("axtls")]\n public static extern/;
$line =~ s/uint32_t/uint/g;
$line =~ s/uint8_t \*\*/ref IntPtr /g;
$line =~ s/const uint8_t \* /IntPtr /g;
$line =~ s/const uint8_t \*/byte[] /g; # note: subtle diff
$line =~ s/uint8_t \* ?/byte[] /g;
$line =~ s/uint8_t ?/byte /g;
$line =~ s/const char \* ?/string /g;
$line =~ s/const SSL_CTX \* ?/IntPtr /g;
$line =~ s/SSL_CTX \* ?/IntPtr /g;
$line =~ s/SSLObjLoader \* ?/IntPtr /g;
$line =~ s/const SSL \* ?/IntPtr /g;
$line =~ s/SSL \* ?/IntPtr /g;
$line =~ s/\(void\)/()/g;
}
elsif ($binding == $VBNET)
{
if ($line =~ /EXP_FUNC/)
{
# Procedure or function?
my $invariant = $line =~ /void /;
my $proc = $invariant ? "Sub" : "Function";
($signature_ret_type) = $line =~ /EXP_FUNC (.*) STDCALL/;
$line =~ s/EXP_FUNC .* STDCALL / <DllImport("axtls")> Public Shared $proc _\n /;
$signature_ret_type =~ s/const uint8_t \*/As IntPtr/;
$signature_ret_type =~ s/const char \*/As String/;
$signature_ret_type =~ s/SSL_CTX \*/As IntPtr/;
$signature_ret_type =~ s/SSLObjLoader \*/As IntPtr/;
$signature_ret_type =~ s/SSL \*/As IntPtr/;
$signature_ret_type =~ s/uint8_t/As Byte/;
$signature_ret_type =~ s/int/As Integer/;
$signature_ret_type =~ s/void//;
$signature_ret_type .= "\n End $proc\n\n";
}
$line =~ s/uint32_t (\w+)/ByVal $1 As Integer/g;
$line =~ s/int (\w+)/ByVal $1 As Integer/g;
$line =~ s/uint8_t \*\* ?(\w+)/ByRef $1 As IntPtr/g;
$line =~ s/const uint8_t \* ?(\w+)/ByVal $1() As Byte/g;
$line =~ s/uint8_t \* ?(\w+)/ByVal $1() As Byte/g;
$line =~ s/const char \* ?(\w+)/ByVal $1 As String/g;
$line =~ s/const SSL_CTX \* ?(\w+)/ByVal $1 As IntPtr/g;
$line =~ s/SSL_CTX \* ?(\w+)/ByVal $1 As IntPtr/g;
$line =~ s/SSLObjLoader \* ?(\w+)/ByVal $1 As IntPtr/g;
$line =~ s/const SSL \* ?(\w+)/ByVal $1 As IntPtr/g;
$line =~ s/SSL \* ?(\w+)/ByVal $1 As IntPtr/g;
$line =~ s/void \* ?(\w+)/Byval $1 As IntPtr/g;
$line =~ s/\(void\)/()/g;
$line =~ s/void//g;
$line =~ s/;\n/ $signature_ret_type;/;
}
}
return $line;
}
# Parse input file
sub parseFile
{
my (@file) = @_;
my $line;
my $splitDefine = 0;
my $splitFunctionDeclaration;
my $vb_hack = " ";
my $vb_line_hack = 0;
$skip = 0;
foreach $line (@file)
{
# test for a #define
if (!$skip && $line =~ m/^#define/)
{
$splitDefine = 1 if $line =~ m/\\$/;
if ($binding == $VBNET)
{
$line =~ s/\|/Or/g;
$line =~ s/ 0x/ &H/;
}
my ($name, $value) = $line =~ /#define (\w+) +([^\\]*)[\\]?\n/;
if (defined $name && defined $value)
{
# C# constant translation
if ($binding == $CSHARP)
{
$line = " public const int $name = $value";
}
# VB.NET constant translation
elsif ($binding == $VBNET)
{
$line = " Public Const $name As Integer = $value";
}
}
next if $line =~ /#define/; # ignore any other defines
print DATA_OUT $line;
# check line is not split
next if $splitDefine == 1;
print DATA_OUT ";" if $binding == $CSHARP;
print DATA_OUT "\n";
}
# pick up second line of #define statement
if ($splitDefine)
{
if ($line !~ /\\$/)
{
$line =~ s/$/;/ if $binding == $CSHARP; # add the ";"
}
$line =~ s/ ?\| ?/ Or /g
if ($binding == $VBNET);
# check line is not split
$splitDefine = ($line =~ m/\\$/);
# ignore trailing "\"
$line =~ s/\\$// if $binding == $CSHARP;
$line =~ s/\\$/_/ if $binding == $VBNET;
print DATA_OUT $line;
next;
}
# test for function declaration
if (!$skip && $line =~ /EXP_FUNC/ && $line !~ /\/\*/)
{
$line = transformSignature($line);
$splitFunctionDeclaration = $line !~ /;/;
$line =~ s/;// if ($binding == $VBNET);
$line =~ s/\n$/ _\n/ if ($binding == $VBNET) &&
$splitFunctionDeclaration;
print DATA_OUT $line;
next;
}
if ($splitFunctionDeclaration)
{
$line = transformSignature($line);
$splitFunctionDeclaration = $line !~ /;/;
$line =~ s/;// if ($binding == $VBNET);
$line =~ s/\n/ _\n/ if ($binding == $VBNET) &&
$splitFunctionDeclaration == 1;
print DATA_OUT $line;
next;
}
}
}
#===============================================================
# Determine which module to build from command-line options
use strict;
use Getopt::Std;
my $binding_prefix;
my $binding_suffix;
my $data_file;
my @raw_data;
if (not defined $ARGV[0])
{
goto ouch;
}
if ($ARGV[0] eq "-csharp")
{
print "Generating C# interface file\n";
$binding_prefix = "csharp";
$binding_suffix = "cs";
$binding = $CSHARP;
}
elsif ($ARGV[0] eq "-vbnet")
{
print "Generating VB.NET interface file\n";
$binding_prefix = "vbnet";
$binding_suffix = "vb";
$binding = $VBNET;
}
else
{
ouch:
die "Usage: $0 [-csharp | -vbnet]\n";
}
my $interfaceFile = "$binding_prefix/axInterface.$binding_suffix";
# Input file required to generate 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
if ($binding == $CSHARP || $binding == $VBNET)
{
open(DATA_OUT, ">$interfaceFile") || die("Cannot Open File");
}
# SPEC interface file header
if ($binding == $CSHARP)
{
# generate the C#/C interface file
print DATA_OUT << "END";
// The C# to C interface definition file for the axTLS project
// Do not modify - this file is generated
using System;
using System.Runtime.InteropServices;
namespace axTLS
{
public class axtls
{
END
}
elsif ($binding == $VBNET)
{
# generate the VB.NET/C interface file
print DATA_OUT << "END";
' The VB.NET to C interface definition file for the axTLS project
' Do not modify - this file is generated
Imports System
Imports System.Runtime.InteropServices
Namespace axTLSvb
Public Class axtls
END
}
parseFile(@raw_data);
# finish up
if ($binding == $CSHARP)
{
print DATA_OUT " };\n";
print DATA_OUT "};\n";
}
elsif ($binding == $VBNET)
{
print DATA_OUT " End Class\nEnd Namespace\n";
}
close(DATA_IN);
close(DATA_OUT);
#===============================================================

93
bindings/java/Makefile Normal file
View File

@ -0,0 +1,93 @@
#
# 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 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
include ../../config/makefile.java.conf
all: lib jar
JAR=../../$(STAGE)/axtls.jar
ifdef CONFIG_PLATFORM_WIN32
TARGET=../../$(STAGE)/axtlsj.dll
else
TARGET=../../$(STAGE)/libaxtlsj.so
endif
lib: $(TARGET)
axTLSj_wrap.o : axTLSj_wrap.c
JAVA_FILES= \
axtlsjJNI.java \
axtlsjConstants.java \
axtlsj.java \
SSLReadHolder.java \
SSL.java \
SSLUtil.java \
SSLCTX.java \
SSLServer.java \
SSLClient.java
OBJ=axTLSj_wrap.o
AXOLOTLS_HOME=../..
SSL_HOME=$(AXOLOTLS_HOME)/ssl
CONFIG_HOME=$(AXOLOTLS_HOME)/config
JAVA_CLASSES:=$(JAVA_FILES:%.java=classes/axTLSj/%.class)
ifdef CONFIG_PLATFORM_WIN32
CFLAGS += /I"$(shell cygpath -w $(SSL_HOME))"
CFLAGS += /I"$(shell cygpath -w $(CONFIG_HOME))"
LDFLAGS += axtls.lib /libpath:"../../$(STAGE)"
include ../../config/makefile.post
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) $(LDSHARED) /out:$@ $(OBJ)
else # Not Win32
ifdef CONFIG_PLATFORM_CYGWIN
SSL_HOME:=$(shell cygpath -u $(SSL_HOME))
CONFIG_HOME:=$(shell cygpath -u $(CONFIG_HOME))
endif
CFLAGS += -I$(SSL_HOME)
CFLAGS += -I$(CONFIG_HOME)
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) -L ../../$(STAGE) $(LDSHARED) -o $@ $(OBJ) -laxtls
endif
jar: $(OBJ) $(JAR)
# if we are doing the samples then defer creating the jar until then
$(JAR): $(JAVA_CLASSES)
ifndef CONFIG_JAVA_SAMPLES
jar cvf $@ -C classes axTLSj
else
@if [ ! -f $(JAR) ]; then touch $(JAR); fi
endif
classes/axTLSj/%.class : %.java
javac -d classes -classpath classes $^
clean::
@rm -f $(JAR) $(TARGET) SWIG* axtls* *.i *.c
@rm -fr classes/*

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

@ -0,0 +1,125 @@
/*
* 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
*/
/*
* 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_RC4_128_SHA (0x05)
* - SSL_RC4_128_MD5 (0x04)
*/
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);
}
}

219
bindings/java/SSLCTX.java Normal file
View File

@ -0,0 +1,219 @@
/*
* 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
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
import java.net.*;
/**
* @class SSLCTX
* @ingroup java_api
* @brief A base object for SSLServer/SSLClient.
*/
public class SSLCTX
{
/**
* A reference to the real client/server context.
*/
protected int 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_NO_DEFAULT_KEY: Don't use the default key/certificate. The user
* will load the key/certificate explicitly.
* - 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.
*
* If this option is null, then the default internal private key/
* certificate pair is used (if CONFIG_SSL_USE_DEFAULT_KEY is set).
*
* The resources used by this object are automatically freed.
* @return A client/server context.
*/
protected SSLCTX(int options, int num_sessions)
{
m_ctx = axtlsj.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()
{
axtlsj.ssl_ctx_free(m_ctx);
}
/**
* @brief Read the SSL data stream.
* @param ssl [in] An SSL object reference.
* @param rh [out] After a successful read, the decrypted data can be
* retrieved with rh.getData(). 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 rh before doing any successive ssl calls.
*/
public int read(SSL ssl, SSLReadHolder rh)
{
return axtlsj.ssl_read(ssl.m_ssl, rh);
}
/**
* @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 axtlsj.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 axtlsj.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://java.sun.com/j2se/1.4.2/docs/api">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 = axtlsj.getFd(s);
return new SSL(axtlsj.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 axtlsj.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 axtlsj.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 axtlsj.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 axtlsj.ssl_obj_memory_load(m_ctx, obj_type, data, len, password);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
import java.net.*;
/**
* @class SSLClient
* @ingroup java_api
* @brief The client context.
*
* All client connections are started within a client context.
*/
public class SSLClient extends SSLCTX
{
/**
* @brief Start a new client context.
*
* @see SSLCTX for details.
*/
public SSLClient(int options, int num_sessions)
{
super(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://java.sun.com/j2se/1.4.2/docs/api">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 = axtlsj.getFd(s);
return new SSL(axtlsj.ssl_client_new(m_ctx, client_fd, session_id));
}
}

View File

@ -0,0 +1,49 @@
/*
* 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
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
/**
* @class SSLReadHolder
* @ingroup java_api
* @brief A holder for data read in an SSL read.
*/
public class SSLReadHolder
{
/**
* @brief Contruct a new read holder object.
*/
public SSLReadHolder()
{
m_buf = null;
}
/**
* @brief Retrieve the reference to the read data.
*/
public byte[] getData()
{
return m_buf;
}
private byte[] m_buf;
}

View File

@ -0,0 +1,60 @@
/*
* 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
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
import java.net.*;
/**
* @class SSLServer
* @ingroup java_api
* @brief The server context.
*
* All server connections are started within a server context.
*/
public class SSLServer extends SSLCTX
{
/**
* @brief Start a new server context.
*
* @see SSLCTX for details.
*/
public SSLServer(int options, int num_sessions)
{
super(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://java.sun.com/j2se/1.4.2/docs/api">Socket</A> object.
* @return An SSL object reference.
*/
public SSL connect(Socket s)
{
int client_fd = axtlsj.getFd(s);
return new SSL(axtlsj.ssl_server_new(m_ctx, client_fd));
}
}

104
bindings/java/SSLUtil.java Normal file
View File

@ -0,0 +1,104 @@
/*
* 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
*/
/*
* A wrapper around the unmanaged interface to give a semi-decent Java API
*/
package axTLSj;
import java.io.*;
import java.util.*;
/**
* @class SSLUtil
* @ingroup java_api
* @brief Some global helper functions.
*
*/
public class SSLUtil
{
/**
* @brief Load up the ddl/shared library
*/
static
{
System.loadLibrary("axtlsj");
}
/**
* @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 axtlsj.ssl_get_config(axtlsj.SSL_BUILD_MODE);
}
/**
* @brief Return the number of chained certificates that the client/server
* supports.
* @return The number of supported client/server certificates.
*/
public static int maxCerts()
{
return axtlsj.ssl_get_config(axtlsj.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 axtlsj.ssl_get_config(axtlsj.SSL_MAX_CA_CERT_CFG_OFFSET);
}
/**
* @brief Indicate if PEM is supported.
* @return true if PEM supported.
*/
public static boolean hasPEM()
{
return axtlsj.ssl_get_config(axtlsj.SSL_HAS_PEM) > 0 ? true : false;
}
/**
* @brief Display the text string of the error.
* @param error_code [in] The integer error code.
* @see ssl.h for the error code list.
*/
public static void displayError(int error_code)
{
axtlsj.ssl_display_error(error_code);
}
/**
* @brief Return the version of the axTLS project.
*/
public static String version()
{
return axtlsj.ssl_version();
}
}

81
bindings/perl/Makefile Normal file
View File

@ -0,0 +1,81 @@
#
# 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 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: lib
ifdef CONFIG_PLATFORM_WIN32
TARGET=../../$(STAGE)/axtlsp.dll
else
TARGET=../../$(STAGE)/libaxtlsp.so
endif
ifneq ($(MAKECMDGOALS), clean)
ifdef CONFIG_PLATFORM_WIN32
PERL5_CORE:=$(shell cygpath -w "$(CONFIG_PERL_CORE)")
else
PERL5_CORE= $(shell perl -e 'use Config; print $$Config{archlib};')/CORE
endif
all: test_perl
test_perl:
@if ! [ -d "$(PERL5_CORE)" ]; then \
echo "*** Error: Perl not installed at $(CONFIG_PERL_CORE) - go to " \
"http://www.cpan.org/authors/id/G/GR/GRAHAMC/SiePerl-5.8.0-bin-1.0-Win32.INSTALL.exe" && exit 1; \
fi
endif
lib: $(TARGET)
AXTLS_HOME=../..
SSL_HOME=$(AXTLS_HOME)/ssl
CONFIG_HOME=$(AXTLS_HOME)/config
OBJ:=axTLSp_wrap.o
include ../../config/makefile.post
ifndef CONFIG_PLATFORM_WIN32 # Linux/Unix/Cygwin
#
# Could have used libperl.a, but it increases the library to over 1MB, so just
# use libperl.so. But this needs to be in the shared library path for things to
# work.
#
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) -L ../../$(STAGE) -L$(PERL5_CORE) $(LDSHARED) -o $@ $(OBJ) -laxtls -lperl
ifdef CONFIG_PLATFORM_CYGWIN
cd ../../$(STAGE); ln -sf $(notdir $@) axtlsp.dll
endif
@install axtlsp.pm ../../$(STAGE)
CFLAGS += -D__USE_GNU -I$(CONFIG_HOME) -I$(SSL_HOME) -I$(PERL5_CORE)
else
CFLAGS += /I"`cygpath -w $(CONFIG_HOME)`" /I"`cygpath -w $(SSL_HOME)`"
CFLAGS += /I"$(PERL5_CORE)"
LDFLAGS += $(CONFIG_PERL_LIB) /libpath:"$(PERL5_CORE)" axtls.lib /libpath:"../../$(STAGE)"
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) $(LDSHARED) /out:$@ $(OBJ)
install axtlsp.pm ../../$(STAGE)
endif # WIN32
clean::
@rm -f $(TARGET) axtls* *.i axTLSp* *.c .depend ../../$(STAGE)/axtlsp.pm

23
bindings/vbnet/Makefile Normal file
View File

@ -0,0 +1,23 @@
#
# 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 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
clean::
@rm -f axssl* axInterface.vb

179
bindings/vbnet/axTLSvb.vb Normal file
View File

@ -0,0 +1,179 @@
'
' 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 As ) 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
'
'
' A wrapper around the unmanaged Integererface to give a semi-decent VB.NET API
'
Imports System
Imports System.Runtime.InteropServices
Imports System.Net.Sockets
Imports axTLSvb
Namespace axTLSvb
Public Class SSL
Public m_ssl As IntPtr
Public Sub New(ByRef ip As IntPtr)
m_ssl = ip
End Sub
Public Sub Dispose()
axtls.ssl_free(m_ssl)
End Sub
Public Function HandshakeStatus() As Integer
Return axtls.ssl_handshake_status(m_ssl)
End Function
Public Function GetCipherId() As Byte
Return axtls.ssl_get_cipher_id(m_ssl)
End Function
Public Function GetSessionId() As Byte()
Dim result(axtls.SSL_SESSION_ID_SIZE) As Byte
Dim ptr As IntPtr = axtls.ssl_get_session_id(m_ssl)
Marshal.Copy(ptr, result, 0, axtls.SSL_SESSION_ID_SIZE)
Return result
End Function
Public Function GetCertificateDN(component As Integer) As String
Return axtls.ssl_get_cert_dn(m_ssl, component)
End Function
End Class
Public Class SSLUtil
Private dummy As Integer ' need something here
Public Shared Function BuildMode() As Integer
Return axtls.ssl_get_config(axtls.SSL_BUILD_MODE)
End Function
Public Shared Function MaxCerts() As Integer
Return axtls.ssl_get_config(axtls.SSL_MAX_CERT_CFG_OFFSET)
End Function
Public Shared Function MaxCACerts() As Integer
Return axtls.ssl_get_config(axtls.SSL_MAX_CA_CERT_CFG_OFFSET)
End Function
Public Shared Function HasPEM() As Boolean
If axtls.ssl_get_config(axtls.SSL_HAS_PEM) > 0 Then
Return True
Else
Return False
End If
End Function
Public Shared Sub DisplayError(ByVal error_code As Integer)
axtls.ssl_display_error(error_code)
End Sub
Public Shared Function Version() As String
Return axtls.ssl_version()
End Function
End Class
Public Class SSLCTX
Protected m_ctx As IntPtr
Protected Sub New(ByVal options As Integer, _
ByVal num_sessions As Integer)
m_ctx = axtls.ssl_ctx_new(options, num_sessions)
End Sub
Public Sub Dispose()
axtls.ssl_ctx_free(m_ctx)
End Sub
Public Function Read(ByVal ssl As SSL, ByRef in_data As Byte()) As Integer
Dim ptr As IntPtr = IntPtr.Zero
Dim ret as Integer = axtls.ssl_read(ssl.m_ssl, ptr)
If ret > axtls.SSL_OK Then
ReDim in_data(ret)
Marshal.Copy(ptr, in_data, 0, ret)
Else
in_data = Nothing
End If
Return ret
End Function
Public Function Write(ByVal ssl As SSL, _
ByVal data As Byte(), len As Integer) As Integer
Return axtls.ssl_write(ssl.m_ssl, data, len)
End Function
Public Function Find(ByVal s As Socket) As SSL
Dim client_fd As Integer = s.Handle.ToInt32()
Return New SSL(axtls.ssl_find(m_ctx, client_fd))
End Function
Public Function VerifyCert(ByVal ssl As SSL) As Integer
Return axtls.ssl_verify_cert(ssl.m_ssl)
End Function
Public Function Renegotiate(ByVal ssl As SSL) As Integer
Return axtls.ssl_renegotiate(ssl.m_ssl)
End Function
Public Function ObjLoad(ByVal obj_type As Integer, _
ByVal filename As String, _
password As String) As Integer
Return axtls.ssl_obj_load(m_ctx, obj_type, filename, password)
End Function
Public Function ObjLoad(ByVal obj_type As Integer, _
ByVal data As Byte(), ByVal len As Integer, _
password As String) As Integer
Return axtls.ssl_obj_memory_load( _
m_ctx, obj_type, data, len, password)
End Function
End Class
Public Class SSLServer
Inherits SSLCTX
Public Sub New(ByVal options As Integer, _
ByVal num_sessions As Integer)
MyBase.New(options, num_sessions)
End Sub
Public Function Connect(ByVal s As Socket) As SSL
Dim client_fd As Integer = s.Handle.ToInt32()
Return New SSL(axtls.ssl_server_new(m_ctx, client_fd))
End Function
End Class
Public Class SSLClient
Inherits SSLCTX
Public Sub New(ByVal options As Integer, _
ByVal num_sessions As Integer)
MyBase.New(options, num_sessions)
End Sub
Public Function Connect(ByVal s As Socket, _
ByVal session_id As Byte()) As SSL
Dim client_fd As Integer = s.Handle.ToInt32()
Return New SSL( axtls.ssl_client_new(m_ctx, client_fd, session_id))
End Function
End Class
End Namespace

11
config/.config.tmp Normal file
View File

@ -0,0 +1,11 @@
deps_config := \
ssl/BigIntConfig.in \
samples/Config.in \
bindings/Config.in \
httpd/Config.in \
ssl/Config.in \
config/Config.in
.config include/config.h: $(deps_config)
$(deps_config):

120
config/Config.in Normal file
View File

@ -0,0 +1,120 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
mainmenu "axTLS Configuration"
config HAVE_DOT_CONFIG
bool
default y
choice
prompt "Platform"
default CONFIG_PLATFORM_LINUX
config CONFIG_PLATFORM_LINUX
bool "Linux"
config CONFIG_PLATFORM_CYGWIN
bool "Cygwin"
config CONFIG_PLATFORM_SOLARIS
bool "Solaris"
config CONFIG_PLATFORM_WIN32
bool "Win32"
endchoice
menu "General Configuration"
config PREFIX
string "axTLS installation prefix"
depends on !CONFIG_PLATFORM_WIN32
default "/usr/local"
help
Define your directory to install axTLS files/subdirs in.
config CONFIG_DEBUG
bool "Build axTLS with Debugging symbols"
default n
help
Say Y here if you wish to compile axTLS with debugging symbols.
This will allow you to use a debugger to examine axTLS internals.
This increases the size of the binary considerably and should only be
used when doing development.
If you are doing development and want to debug axTLS, answer Y.
Most people should answer N.
menu "Microsoft Compiler Options"
depends on CONFIG_PLATFORM_WIN32
choice
prompt "Compiler"
depends on CONFIG_PLATFORM_WIN32
default CONFIG_VISUAL_STUDIO_7_0
config CONFIG_VISUAL_STUDIO_6_0
bool "Visual Studio 6.0 (VC98)"
help
Use Microsoft's Visual Studio 6.0 platform.
config CONFIG_VISUAL_STUDIO_7_0
bool "Visual Studio 7.0 (2003)"
help
Use Microsoft's Visual Studio 2003 platform.
config CONFIG_VISUAL_STUDIO_8_0
bool "Visual Studio 8.0 (2005)"
help
Use Microsoft's Visual Studio 2005 platform.
endchoice
config CONFIG_VISUAL_STUDIO_6_0_BASE
string "Base"
depends on CONFIG_VISUAL_STUDIO_6_0
default "c:\\Program Files\\Microsoft Visual Studio"
config CONFIG_VISUAL_STUDIO_7_0_BASE
string "Base"
depends on CONFIG_VISUAL_STUDIO_7_0
default "c:\\Program Files\\Microsoft Visual Studio .NET 2003"
config CONFIG_VISUAL_STUDIO_8_0_BASE
string "Base"
depends on CONFIG_VISUAL_STUDIO_8_0
default "c:\\Program Files\\Microsoft Visual Studio 8"
endmenu
config CONFIG_EXTRA_CFLAGS_OPTIONS
string "Any extra CFLAGS options for the compiler?"
help
Do you want to pass any extra CFLAGS options to the compiler as
you build axTLS? If so, this is the option for you... For
example, if you want to add some simple compiler switches (like
-march=i686), or check for warnings using -Werror, just those
options here.
config CONFIG_EXTRA_LDFLAGS_OPTIONS
string "Any extra LDFLAGS options for the compiler?"
help
Do you want to pass any extra LDFLAGS options to the compiler?
endmenu
source ssl/Config.in
config CONFIG_AXHTTPD
bool "Enable HTTP/HTTPS Web Server"
default y
help
Build the AXHTTPD web server
source httpd/Config.in
source bindings/Config.in
source samples/Config.in
source ssl/BigIntConfig.in

247
config/JMeter.jmx Executable file
View File

@ -0,0 +1,247 @@
<jmeterTestPlan version="1.2" properties="1.8">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="axhttpd Test Plan" enabled="true">
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
<boolProp name="TestPlan.serialize_threadgroups">true</boolProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<stringProp name="TestPlan.comments"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Test 1" enabled="true">
<longProp name="ThreadGroup.start_time">1152004173000</longProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<stringProp name="LoopController.loops">10</stringProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
<longProp name="ThreadGroup.end_time">1152004173000</longProp>
<stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Normal" enabled="true">
<stringProp name="HTTPSampler.path">/index.html</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.port">80</stringProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
</HTTPSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Test 2" enabled="true">
<longProp name="ThreadGroup.start_time">1152004173000</longProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<stringProp name="LoopController.loops">10</stringProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
<longProp name="ThreadGroup.end_time">1152004173000</longProp>
<stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="RC4" enabled="true">
<stringProp name="HTTPSampler.path">/index.html</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<stringProp name="HTTPSampler.protocol">HTTPS</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.port">443</stringProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
</HTTPSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Test 3" enabled="true">
<longProp name="ThreadGroup.start_time">1152004173000</longProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<stringProp name="LoopController.loops">10</stringProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
<longProp name="ThreadGroup.end_time">1152004173000</longProp>
<stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="AES128" enabled="true">
<stringProp name="HTTPSampler.path">/index.html</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<stringProp name="HTTPSampler.protocol">HTTPS</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.port">2443</stringProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
</HTTPSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Test 4" enabled="true">
<longProp name="ThreadGroup.start_time">1152004173000</longProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<stringProp name="LoopController.loops">10</stringProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
<longProp name="ThreadGroup.end_time">1152004173000</longProp>
<stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="AES256" enabled="true">
<stringProp name="HTTPSampler.path">/index.html</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<stringProp name="HTTPSampler.protocol">HTTPS</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.port">3443</stringProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
</HTTPSampler>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Test 5" enabled="true">
<longProp name="ThreadGroup.start_time">1152004173000</longProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<stringProp name="LoopController.loops">10</stringProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
<longProp name="ThreadGroup.end_time">1152004173000</longProp>
<stringProp name="ThreadGroup.on_sample_error">stopthread</stringProp>
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="Skeleton (RC4)" enabled="true">
<stringProp name="HTTPSampler.path">/index.html</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<stringProp name="HTTPSampler.protocol">HTTPS</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.port">1443</stringProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.mimetype"></stringProp>
<stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
<stringProp name="HTTPSampler.monitor">false</stringProp>
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.FILE_NAME"></stringProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
</HTTPSampler>
<hashTree/>
</hashTree>
<ResultCollector guiclass="StatGraphVisualizer" testclass="ResultCollector" testname="Aggregate Graph" enabled="true">
<objProp>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
</value>
<name>saveConfig</name>
</objProp>
<stringProp name="filename"></stringProp>
<boolProp name="ResultCollector.error_logging">false</boolProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false">
<objProp>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
</value>
<name>saveConfig</name>
</objProp>
<stringProp name="filename"></stringProp>
<boolProp name="ResultCollector.error_logging">false</boolProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</jmeterTestPlan>

220
config/Rules.mak Normal file
View File

@ -0,0 +1,220 @@
# Rules.make for busybox
#
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
#
# Licensed under GPLv2, see the file LICENSE in this tarball for details.
#
# Pull in the user's busybox configuration
ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),)
-include $(top_builddir)/.config
endif
#--------------------------------------------------------
PROG := busybox
MAJOR_VERSION :=1
MINOR_VERSION :=1
SUBLEVEL_VERSION:=0
EXTRAVERSION :=
VERSION :=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL_VERSION)$(EXTRAVERSION)
BUILDTIME := $(shell TZ=UTC date -u "+%Y.%m.%d-%H:%M%z")
#--------------------------------------------------------
# With a modern GNU make(1) (highly recommended, that's what all the
# developers use), all of the following configuration values can be
# overridden at the command line. For example:
# make CROSS=powerpc-linux- top_srcdir="$HOME/busybox" PREFIX=/mnt/app
#--------------------------------------------------------
# If you are running a cross compiler, you will want to set 'CROSS'
# to something more interesting... Target architecture is determined
# by asking the CC compiler what arch it compiles things for, so unless
# your compiler is broken, you should not need to specify TARGET_ARCH
CROSS =$(subst ",, $(strip $(CROSS_COMPILER_PREFIX)))
CC = $(CROSS)gcc
AR = $(CROSS)ar
AS = $(CROSS)as
LD = $(CROSS)ld
NM = $(CROSS)nm
STRIP = $(CROSS)strip
CPP = $(CC) -E
# MAKEFILES = $(top_builddir)/.config
RM = rm
RM_F = $(RM) -f
LN = ln
LN_S = $(LN) -s
MKDIR = mkdir
MKDIR_P = $(MKDIR) -p
MV = mv
CP = cp
# What OS are you compiling busybox for? This allows you to include
# OS specific things, syscall overrides, etc.
TARGET_OS=linux
# Select the compiler needed to build binaries for your development system
HOSTCC = gcc
HOSTCFLAGS= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
LC_ALL:= C
# If you want to add some simple compiler switches (like -march=i686),
# especially from the command line, use this instead of CFLAGS directly.
# For optimization overrides, it's better still to set OPTIMIZATION.
CFLAGS_EXTRA=$(subst ",, $(strip $(EXTRA_CFLAGS_OPTIONS)))
# To compile vs some other alternative libc, you may need to use/adjust
# the following lines to meet your needs...
#
# If you are using Red Hat 6.x with the compatible RPMs (for developing under
# Red Hat 5.x and glibc 2.0) uncomment the following. Be sure to read about
# using the compatible RPMs (compat-*) at http://www.redhat.com !
#LIBCDIR:=/usr/i386-glibc20-linux
#
# For other libraries, you are on your own. But these may (or may not) help...
#LDFLAGS+=-nostdlib
#LIBRARIES:=$(LIBCDIR)/lib/libc.a -lgcc
#CROSS_CFLAGS+=-nostdinc -I$(LIBCDIR)/include -I$(GCCINCDIR) -funsigned-char
#GCCINCDIR:=$(shell gcc -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp")
WARNINGS=-Wall -Wstrict-prototypes -Wshadow
CFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir)
ARFLAGS=cru
# gcc centric. Perhaps fiddle with findstring gcc,$(CC) for the rest
# get the CC MAJOR/MINOR version
CC_MAJOR:=$(shell printf "%02d" $(shell echo __GNUC__ | $(CC) -E -xc - | tail -n 1))
CC_MINOR:=$(shell printf "%02d" $(shell echo __GNUC_MINOR__ | $(CC) -E -xc - | tail -n 1))
#--------------------------------------------------------
export VERSION BUILDTIME HOSTCC HOSTCFLAGS CROSS CC AR AS LD NM STRIP CPP
ifeq ($(strip $(TARGET_ARCH)),)
TARGET_ARCH:=$(shell $(CC) -dumpmachine | sed -e s'/-.*//' \
-e 's/i.86/i386/' \
-e 's/sparc.*/sparc/' \
-e 's/arm.*/arm/g' \
-e 's/m68k.*/m68k/' \
-e 's/ppc/powerpc/g' \
-e 's/v850.*/v850/g' \
-e 's/sh[234]/sh/' \
-e 's/mips-.*/mips/' \
-e 's/mipsel-.*/mipsel/' \
-e 's/cris.*/cris/' \
)
endif
# A nifty macro to make testing gcc features easier
check_gcc=$(shell \
if [ "$(1)" != "" ]; then \
if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \
then echo "$(1)"; else echo "$(2)"; fi \
fi)
# Setup some shortcuts so that silent mode is silent like it should be
ifeq ($(subst s,,$(MAKEFLAGS)),$(MAKEFLAGS))
export MAKE_IS_SILENT=n
SECHO=@echo
else
export MAKE_IS_SILENT=y
SECHO=-@false
endif
CFLAGS+=$(call check_gcc,-funsigned-char,)
#--------------------------------------------------------
# Arch specific compiler optimization stuff should go here.
# Unless you want to override the defaults, do not set anything
# for OPTIMIZATION...
# use '-Os' optimization if available, else use -O2
OPTIMIZATION:=$(call check_gcc,-Os,-O2)
# Some nice architecture specific optimizations
ifeq ($(strip $(TARGET_ARCH)),arm)
OPTIMIZATION+=-fstrict-aliasing
endif
ifeq ($(strip $(TARGET_ARCH)),i386)
OPTIMIZATION+=$(call check_gcc,-march=i386,)
OPTIMIZATION+=$(call check_gcc,-mpreferred-stack-boundary=2,)
OPTIMIZATION+=$(call check_gcc,-falign-functions=0 -falign-jumps=0 -falign-loops=0,\
-malign-functions=0 -malign-jumps=0 -malign-loops=0)
endif
OPTIMIZATIONS:=$(OPTIMIZATION) -fomit-frame-pointer
#
#--------------------------------------------------------
# If you're going to do a lot of builds with a non-vanilla configuration,
# it makes sense to adjust parameters above, so you can type "make"
# by itself, instead of following it by the same half-dozen overrides
# every time. The stuff below, on the other hand, is probably less
# prone to casual user adjustment.
#
ifeq ($(strip $(CONFIG_LFS)),y)
# For large file summit support
CFLAGS+=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
endif
ifeq ($(strip $(CONFIG_DMALLOC)),y)
# For testing mem leaks with dmalloc
CFLAGS+=-DDMALLOC
LIBRARIES:=-ldmalloc
else
ifeq ($(strip $(CONFIG_EFENCE)),y)
LIBRARIES:=-lefence
endif
endif
ifeq ($(strip $(CONFIG_DEBUG)),y)
CFLAGS +=$(WARNINGS) -g -D_GNU_SOURCE
LDFLAGS +=-Wl,-warn-common
STRIPCMD:=/bin/true -Not_stripping_since_we_are_debugging
else
CFLAGS+=$(WARNINGS) $(OPTIMIZATIONS) -D_GNU_SOURCE -DNDEBUG
LDFLAGS += -Wl,-warn-common
STRIPCMD:=$(STRIP) -s --remove-section=.note --remove-section=.comment
endif
ifeq ($(strip $(CONFIG_STATIC)),y)
LDFLAGS += --static
endif
ifeq ($(strip $(CONFIG_SELINUX)),y)
LIBRARIES += -lselinux
endif
ifeq ($(strip $(PREFIX)),)
PREFIX:=`pwd`/_install
endif
# Additional complications due to support for pristine source dir.
# Include files in the build directory should take precedence over
# the copy in top_srcdir, both during the compilation phase and the
# shell script that finds the list of object files.
# Work in progress by <ldoolitt@recycle.lbl.gov>.
OBJECTS:=$(APPLET_SOURCES:.c=.o) busybox.o usage.o applets.o
CFLAGS += $(CROSS_CFLAGS)
ifdef BB_INIT_SCRIPT
CFLAGS += -DINIT_SCRIPT='"$(BB_INIT_SCRIPT)"'
endif
# Put user-supplied flags at the end, where they
# have a chance of winning.
CFLAGS += $(CFLAGS_EXTRA)
#------------------------------------------------------------
# Installation options
ifeq ($(strip $(CONFIG_INSTALL_APPLET_HARDLINKS)),y)
INSTALL_OPTS=--hardlinks
endif
ifeq ($(strip $(CONFIG_INSTALL_APPLET_SYMLINKS)),y)
INSTALL_OPTS=--symlinks
endif
ifeq ($(strip $(CONFIG_INSTALL_APPLET_DONT)),y)
INSTALL_OPTS=
endif
.PHONY: dummy

149
config/axhttpd.aip Executable file
View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT type="Advanced Installer" CreateVersion="3.9" version="4.2" modules="freeware" RootPath="." Language="en">
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="ALLUSERS" Value="2"/>
<ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install &lt;product name&gt;." ValueLocId="*"/>
<ROW Property="ARPPRODUCTICON" Value="controlPanelIcon.exe"/>
<ROW Property="ARPURLINFOABOUT" Value="http://axtls.cerocclub.com.au"/>
<ROW Property="BannerBitmap" Value="default_banner.bmp" Type="1"/>
<ROW Property="DialogBitmap" Value="default_dialog.bmp" Type="1"/>
<ROW Property="Manufacturer" Value="axTLS" ValueLocId="*"/>
<ROW Property="ProductCode" Value="1033:{4708D414-9C0E-46D2-9B67-D6421C9C5F81} "/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="Axhttpd" ValueLocId="*"/>
<ROW Property="ProductVersion" Value="1.1.0"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{93E5623E-740C-449C-9770-EDABD392868D}"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR" IsPseudoRoot="1"/>
<ROW Directory="New_Folder_DIR" Directory_Parent="APPDIR" DefaultDir="include"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="another_dir_DIR" Directory_Parent="test_dir_DIR" DefaultDir="anothe~1|another_dir"/>
<ROW Directory="bin_DIR" Directory_Parent="test_dir_DIR" DefaultDir="bin"/>
<ROW Directory="no_http_DIR" Directory_Parent="test_dir_DIR" DefaultDir="no_http"/>
<ROW Directory="no_ssl_DIR" Directory_Parent="test_dir_DIR" DefaultDir="no_ssl"/>
<ROW Directory="test_dir_DIR" Directory_Parent="www_DIR" DefaultDir="test_dir"/>
<ROW Directory="www_DIR" Directory_Parent="APPDIR" DefaultDir="www"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="another_dir" ComponentId="{3F073789-DB33-40BC-BF88-922C6DF252EC}" Directory_="another_dir_DIR" Attributes="0"/>
<ROW Component="axhttpd.exe" ComponentId="{0AEFFA20-29FA-4304-8227-F9ED0E6B8A0A}" Directory_="APPDIR" Attributes="0" KeyPath="axhttpd.exe" FullKeyPath="APPDIR\axhttpd.exe"/>
<ROW Component="axssl.csharp.exe" ComponentId="{B9373428-79F5-4D77-8924-48D23EF3870E}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.csharp.exe" FullKeyPath="APPDIR\axssl.csharp.exe"/>
<ROW Component="axssl.exe" ComponentId="{E1E96774-7BFC-45B9-BA33-FC0C631921FD}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.exe" FullKeyPath="APPDIR\axssl.exe"/>
<ROW Component="axssl.vbnet.exe" ComponentId="{31F03DA9-E099-4BBD-88B7-4ABBC9F77EFB}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.vbnet.exe" FullKeyPath="APPDIR\axssl.vbnet.exe"/>
<ROW Component="axtls.dll" ComponentId="{4C741E75-A18A-4FC9-972C-C1EF583713EB}" Directory_="APPDIR" Attributes="0" KeyPath="axtls.dll" FullKeyPath="APPDIR\axtls.dll"/>
<ROW Component="axtls.jar" ComponentId="{796CB0A9-6214-4531-A330-9B37420B7799}" Directory_="APPDIR" Attributes="0" KeyPath="axtls.jar" FullKeyPath="APPDIR"/>
<ROW Component="axtlsj.dll" ComponentId="{AB8043C7-8291-4898-B34A-561335956DC1}" Directory_="APPDIR" Attributes="0" KeyPath="axtlsj.dll" FullKeyPath="APPDIR\axtlsj.dll"/>
<ROW Component="bigint.h" ComponentId="{FC3E492B-D4F0-41FB-A977-76F6E9FE9FFE}" Directory_="New_Folder_DIR" Attributes="0" KeyPath="bigint.h" FullKeyPath="APPDIR\include"/>
<ROW Component="favicon.ico" ComponentId="{9A1AB507-100A-470D-A002-CD8262CA4913}" Directory_="www_DIR" Attributes="0" KeyPath="favicon.ico" FullKeyPath="APPDIR\www"/>
<ROW Component="health.sh" ComponentId="{173D7469-C57C-481E-A315-19DA527BA1A5}" Directory_="test_dir_DIR" Attributes="0" KeyPath="health.sh" FullKeyPath="APPDIR\www\test_dir"/>
<ROW Component="htaccess" ComponentId="{F53CB1D5-A3B9-4401-B0BA-B6AB1DA860B7}" Directory_="no_ssl_DIR" Attributes="0" KeyPath="htaccess" FullKeyPath="APPDIR\www\test_dir\no_ssl"/>
<ROW Component="htaccess_1" ComponentId="{953D1999-CC00-4F85-9B48-2CD83ACAE2F9}" Directory_="no_http_DIR" Attributes="0" KeyPath="htaccess_1" FullKeyPath="APPDIR\www\test_dir\no_http"/>
<ROW Component="htaccess_2" ComponentId="{6F181A8B-B313-47E2-AF79-AABFDBD353D8}" Directory_="bin_DIR" Attributes="0" KeyPath="htaccess_2" FullKeyPath="APPDIR\www\test_dir\bin"/>
<ROW Component="htpasswd.exe" ComponentId="{9FE1AAD2-4E35-443A-AAE5-3A7D03A52AAA}" Directory_="APPDIR" Attributes="0" KeyPath="htpasswd.exe" FullKeyPath="APPDIR\htpasswd.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="axhttpd.exe axssl.csharp.exe axssl.exe axssl.vbnet.exe axtls.dll axtls.jar axtlsj.dll favicon.ico bigint.h health.sh htpasswd.exe another_dir htaccess htaccess_2 htaccess_1"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="axhttpd.exe" Component_="axhttpd.exe" FileName="axhttpd.exe" Attributes="0" SourcePath="..\_stage\axhttpd.exe" SelfReg="false" Sequence="1"/>
<ROW File="axssl.csharp.exe" Component_="axssl.csharp.exe" FileName="axsslc~1.exe|axssl.csharp.exe" Attributes="0" SourcePath="..\_stage\axssl.csharp.exe" SelfReg="false" Sequence="2"/>
<ROW File="axssl.exe" Component_="axssl.exe" FileName="axssl.exe" Attributes="0" SourcePath="..\_stage\axssl.exe" SelfReg="false" Sequence="3"/>
<ROW File="axssl.vbnet.exe" Component_="axssl.vbnet.exe" FileName="axsslv~1.exe|axssl.vbnet.exe" Attributes="0" SourcePath="..\_stage\axssl.vbnet.exe" SelfReg="false" Sequence="4"/>
<ROW File="axtls.dll" Component_="axtls.dll" FileName="axtls.dll" Attributes="0" SourcePath="..\_stage\axtls.dll" SelfReg="false" Sequence="5"/>
<ROW File="axtls.jar" Component_="axtls.jar" FileName="axtls.jar" Attributes="0" SourcePath="..\_stage\axtls.jar" SelfReg="false" Sequence="6"/>
<ROW File="axtls.lib" Component_="axtls.jar" FileName="axtls.lib" Attributes="0" SourcePath="..\_stage\axtls.lib" SelfReg="false" Sequence="7"/>
<ROW File="axtls.static.lib" Component_="axtls.jar" FileName="axtlss~1.lib|axtls.static.lib" Attributes="0" SourcePath="..\_stage\axtls.static.lib" SelfReg="false" Sequence="8"/>
<ROW File="axtlsj.dll" Component_="axtlsj.dll" FileName="axtlsj.dll" Attributes="0" SourcePath="..\_stage\axtlsj.dll" SelfReg="false" Sequence="9"/>
<ROW File="bigint.h" Component_="bigint.h" FileName="bigint.h" Attributes="0" SourcePath="..\ssl\bigint.h" SelfReg="false" Sequence="16"/>
<ROW File="bigint_impl.h" Component_="bigint.h" FileName="bigint~1.h|bigint_impl.h" Attributes="0" SourcePath="..\ssl\bigint_impl.h" SelfReg="false" Sequence="13"/>
<ROW File="crypto.h" Component_="bigint.h" FileName="crypto.h" Attributes="0" SourcePath="..\ssl\crypto.h" SelfReg="false" Sequence="14"/>
<ROW File="favicon.ico" Component_="favicon.ico" FileName="favicon.ico" Attributes="0" SourcePath="..\www\favicon.ico" SelfReg="false" Sequence="10"/>
<ROW File="health.sh" Component_="health.sh" FileName="health.sh" Attributes="0" SourcePath="..\www\test_dir\health.sh" SelfReg="false" Sequence="18"/>
<ROW File="htaccess" Component_="htaccess" FileName="htacce~1|.htaccess" Attributes="0" SourcePath="..\www\test_dir\no_ssl\.htaccess" SelfReg="false" Sequence="22"/>
<ROW File="htaccess_1" Component_="htaccess_1" FileName="htacce~1|.htaccess" Attributes="0" SourcePath="..\www\test_dir\no_http\.htaccess" SelfReg="false" Sequence="25"/>
<ROW File="htaccess_2" Component_="htaccess_2" FileName="htacce~1|.htaccess" Attributes="0" SourcePath="..\www\test_dir\bin\.htaccess" SelfReg="false" Sequence="24"/>
<ROW File="htpasswd" Component_="htaccess_1" FileName="htpass~1|.htpasswd" Attributes="0" SourcePath="..\www\test_dir\no_http\.htpasswd" SelfReg="false" Sequence="26"/>
<ROW File="htpasswd.exe" Component_="htpasswd.exe" FileName="htpasswd.exe" Attributes="0" SourcePath="..\_stage\htpasswd.exe" SelfReg="false" Sequence="21"/>
<ROW File="index.html" Component_="favicon.ico" FileName="index~1.htm|index.html" Attributes="0" SourcePath="..\www\index.html" SelfReg="false" Sequence="11"/>
<ROW File="index.html_1" Component_="htaccess" FileName="index~1.htm|index.html" Attributes="0" SourcePath="..\www\test_dir\no_ssl\index.html" SelfReg="false" Sequence="23"/>
<ROW File="index.html_2" Component_="htaccess_1" FileName="index~1.htm|index.html" Attributes="0" SourcePath="..\www\test_dir\no_http\index.html" SelfReg="false" Sequence="27"/>
<ROW File="os_port.h" Component_="bigint.h" FileName="os_port.h" Attributes="0" SourcePath="..\ssl\os_port.h" SelfReg="false" Sequence="17"/>
<ROW File="some_text.txt" Component_="health.sh" FileName="some_t~1.txt|some_text.txt" Attributes="0" SourcePath="..\www\test_dir\some_text.txt" SelfReg="false" Sequence="19"/>
<ROW File="ssl.h" Component_="bigint.h" FileName="ssl.h" Attributes="0" SourcePath="..\ssl\ssl.h" SelfReg="false" Sequence="12"/>
<ROW File="test_cgi.php" Component_="health.sh" FileName="test_cgi.php" Attributes="0" SourcePath="..\www\test_dir\test_cgi.php" SelfReg="false" Sequence="20"/>
<ROW File="tls1.h" Component_="bigint.h" FileName="tls1.h" Attributes="0" SourcePath="..\ssl\tls1.h" SelfReg="false" Sequence="15"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;ui.ail&gt;"/>
<ROW Path="&lt;ui_en.ail&gt;"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="FolderDlg.aip" Path="&lt;FolderDlg.aip&gt;"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;StaticUIStrings.aip&gt;"/>
<ROW Fragment="UI.aip" Path="&lt;UI.aip&gt;"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="default_banner.bmp" SourcePath="&lt;default-banner.bmp&gt;"/>
<ROW Name="default_dialog.bmp" SourcePath="&lt;default-dialog.bmp&gt;"/>
<ROW Name="launcher.dll" SourcePath="&lt;launcher.dll&gt;"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
<ATTRIBUTE name="FixedSizeBitmaps" value="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
<ROW Dialog_="FolderDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL" Ordering="3"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>
<ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="2"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="1"/>
<ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
<ROW Directory_="another_dir_DIR" Component_="another_dir"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="1" Source="launcher.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_RESTORE_LOCATION" Type="1" Source="launcher.dll" Target="RestoreLocation"/>
<ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="controlPanelIcon.exe" SourcePath="..\www\favicon.ico" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
<ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/>
<ROW Action="AI_STORE_LOCATION" Condition="Not Installed" Sequence="1545"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1300"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="740"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiMediaComponent">
<ATTRIBUTE name="Compress" value="1"/>
<ATTRIBUTE name="FirstMediaSize" value="0"/>
<ATTRIBUTE name="FirstMediaSizeUnit" value="0"/>
<ATTRIBUTE name="InstallationType" value="0"/>
<ATTRIBUTE name="MediaSize" value="0"/>
<ATTRIBUTE name="MediaSizeUnit" value="0"/>
<ATTRIBUTE name="Package" value="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="axhttpd.exe" Directory_="SHORTCUTDIR" Name="axhttpd" Component_="axhttpd.exe" Target="[#axhttpd.exe]" Description="axhttpd.exe" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="axssl_client" Directory_="SHORTCUTDIR" Name="axsslc~1|axssl client" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_client" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="axssl_server" Directory_="SHORTCUTDIR" Name="axssls~1|axssl server" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_server" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
<ROW UpgradeCode="UpgradeCode" VersionMax="ProductVersion" Attributes="1025"/>
<ROW UpgradeCode="UpgradeCode" VersionMin="ProductVersion" Attributes="2"/>
</COMPONENT>
</DOCUMENT>

BIN
config/axtls.RES Normal file

Binary file not shown.

32
config/axtls.rc Normal file
View File

@ -0,0 +1,32 @@
//Microsoft Visual C++ generated resource script.
//
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_AXTLS ICON "../www/favicon.ico"
#endif
/////////////////////////////////////////////////////////////////////////////

106
config/config.h Normal file
View File

@ -0,0 +1,106 @@
/*
* Automatically generated header file: don't edit
*/
#define HAVE_DOT_CONFIG 1
#undef CONFIG_PLATFORM_LINUX
#define CONFIG_PLATFORM_CYGWIN 1
#undef CONFIG_PLATFORM_SOLARIS
#undef CONFIG_PLATFORM_WIN32
/*
* General Configuration
*/
#define PREFIX "/usr/local"
#undef CONFIG_DEBUG
#undef CONFIG_VISUAL_STUDIO_6_0
#undef CONFIG_VISUAL_STUDIO_7_0
#undef CONFIG_VISUAL_STUDIO_8_0
#define CONFIG_VISUAL_STUDIO_6_0_BASE ""
#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
/*
* SSL Library
*/
#undef CONFIG_SSL_SERVER_ONLY
#undef CONFIG_SSL_CERT_VERIFICATION
#undef CONFIG_SSL_ENABLE_CLIENT
#define CONFIG_SSL_FULL_MODE 1
#undef CONFIG_SSL_SKELETON_MODE
#undef CONFIG_SSL_PROT_LOW
#define CONFIG_SSL_PROT_MEDIUM 1
#undef CONFIG_SSL_PROT_HIGH
#define CONFIG_SSL_USE_DEFAULT_KEY 1
#define CONFIG_SSL_ENABLE_V23_HANDSHAKE 1
#define CONFIG_SSL_HAS_PEM 1
#define CONFIG_SSL_USE_PKCS12 1
#define CONFIG_SSL_EXPIRY_TIME 24
#define CONFIG_X509_MAX_CA_CERTS 4
#define CONFIG_SSL_MAX_CERTS 2
#undef CONFIG_SSL_CTX_MUTEXING
#define CONFIG_USE_DEV_URANDOM 1
#undef CONFIG_WIN32_USE_CRYPTO_LIB
#undef CONFIG_OPENSSL_COMPATIBLE
#undef CONFIG_PERFORMANCE_TESTING
#undef CONFIG_SSL_TEST
#define CONFIG_AXHTTPD 1
/*
* Axhttpd Configuration
*/
#undef CONFIG_HTTP_STATIC_BUILD
#define CONFIG_HTTP_PORT 80
#define CONFIG_HTTP_HTTPS_PORT 443
#define CONFIG_HTTP_SESSION_CACHE_SIZE 5
#define CONFIG_HTTP_WEBROOT "../www"
#define CONFIG_HTTP_TIMEOUT 300
#undef CONFIG_HTTP_HAS_CGI
#define CONFIG_HTTP_CGI_EXTENSIONS ""
#undef CONFIG_HTTP_DIRECTORIES
#undef CONFIG_HTTP_HAS_AUTHORIZATION
#undef CONFIG_HTTP_USE_CHROOT
#undef CONFIG_HTTP_CHANGE_UID
#undef CONFIG_HTTP_HAS_IPV6
#undef CONFIG_HTTP_ALL_MIME_TYPES
#define CONFIG_HTTP_VERBOSE 1
#undef CONFIG_HTTP_IS_DAEMON
/*
* Language Bindings
*/
#undef CONFIG_BINDINGS
#undef CONFIG_CSHARP_BINDINGS
#undef CONFIG_VBNET_BINDINGS
#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
#undef CONFIG_JAVA_BINDINGS
#define CONFIG_JAVA_HOME ""
#undef CONFIG_PERL_BINDINGS
#define CONFIG_PERL_CORE ""
#define CONFIG_PERL_LIB ""
/*
* Samples
*/
#define CONFIG_SAMPLES 1
#define CONFIG_C_SAMPLES 1
#undef CONFIG_CSHARP_SAMPLES
#undef CONFIG_VBNET_SAMPLES
#undef CONFIG_JAVA_SAMPLES
#undef CONFIG_PERL_SAMPLES
/*
* BigInt Options
*/
#undef CONFIG_BIGINT_CLASSICAL
#undef CONFIG_BIGINT_MONTGOMERY
#define CONFIG_BIGINT_BARRETT 1
#define CONFIG_BIGINT_CRT 1
#undef CONFIG_BIGINT_KARATSUBA
#define MUL_KARATSUBA_THRESH
#define SQU_KARATSUBA_THRESH
#define CONFIG_BIGINT_SLIDING_WINDOW 1
#define CONFIG_BIGINT_SQUARE 1
#undef CONFIG_BIGINT_CHECK_ON

103
config/linuxconfig Normal file
View File

@ -0,0 +1,103 @@
#
# Automatically generated make config: don't edit
#
HAVE_DOT_CONFIG=y
CONFIG_PLATFORM_LINUX=y
# CONFIG_PLATFORM_CYGWIN is not set
# CONFIG_PLATFORM_SOLARIS is not set
# CONFIG_PLATFORM_WIN32 is not set
#
# General Configuration
#
PREFIX="/usr/local"
# CONFIG_DEBUG is not set
# CONFIG_VISUAL_STUDIO_6_0 is not set
# CONFIG_VISUAL_STUDIO_7_0 is not set
# CONFIG_VISUAL_STUDIO_8_0 is not set
CONFIG_VISUAL_STUDIO_6_0_BASE=""
CONFIG_VISUAL_STUDIO_7_0_BASE=""
CONFIG_VISUAL_STUDIO_8_0_BASE=""
CONFIG_EXTRA_CFLAGS_OPTIONS=""
CONFIG_EXTRA_LDFLAGS_OPTIONS=""
#
# SSL Library
#
# CONFIG_SSL_SERVER_ONLY is not set
# CONFIG_SSL_CERT_VERIFICATION is not set
# CONFIG_SSL_ENABLE_CLIENT is not set
CONFIG_SSL_FULL_MODE=y
# CONFIG_SSL_SKELETON_MODE is not set
# CONFIG_SSL_PROT_LOW is not set
CONFIG_SSL_PROT_MEDIUM=y
# CONFIG_SSL_PROT_HIGH is not set
CONFIG_SSL_USE_DEFAULT_KEY=y
CONFIG_SSL_ENABLE_V23_HANDSHAKE=y
CONFIG_SSL_HAS_PEM=y
CONFIG_SSL_USE_PKCS12=y
CONFIG_SSL_EXPIRY_TIME=24
CONFIG_X509_MAX_CA_CERTS=4
CONFIG_SSL_MAX_CERTS=2
# CONFIG_SSL_CTX_MUTEXING is not set
CONFIG_USE_DEV_URANDOM=y
# CONFIG_WIN32_USE_CRYPTO_LIB is not set
# CONFIG_PERFORMANCE_TESTING is not set
# CONFIG_SSL_TEST is not set
CONFIG_AXHTTPD=y
#
# Axhttpd Configuration
#
# CONFIG_HTTP_STATIC_BUILD is not set
CONFIG_HTTP_HTTPS_PORT=443
CONFIG_HTTP_SESSION_CACHE_SIZE=5
CONFIG_HTTP_WEBROOT="../www"
CONFIG_HTTP_PORT=80
CONFIG_HTTP_TIMEOUT=300
# CONFIG_HTTP_HAS_CGI is not set
CONFIG_HTTP_CGI_EXTENSIONS=""
# CONFIG_HTTP_DIRECTORIES is not set
# CONFIG_HTTP_USE_CHROOT is not set
# CONFIG_HTTP_CHANGE_UID is not set
# CONFIG_HTTP_HAS_IPV6 is not set
CONFIG_HTTP_ALL_MIME_TYPES=y
# CONFIG_HTTP_VERBOSE is not set
# CONFIG_HTTP_IS_DAEMON is not set
#
# Language Bindings
#
CONFIG_BINDINGS=y
# CONFIG_CSHARP_BINDINGS is not set
# CONFIG_VBNET_BINDINGS is not set
CONFIG_DOT_NET_FRAMEWORK_BASE=""
# CONFIG_JAVA_BINDINGS is not set
CONFIG_JAVA_HOME=""
# CONFIG_PERL_BINDINGS is not set
CONFIG_PERL_CORE=""
CONFIG_PERL_LIB=""
#
# Samples
#
CONFIG_SAMPLES=y
CONFIG_C_SAMPLES=y
# CONFIG_CSHARP_SAMPLES is not set
# CONFIG_VBNET_SAMPLES is not set
# CONFIG_JAVA_SAMPLES is not set
# CONFIG_PERL_SAMPLES is not set
#
# BigInt Options
#
# CONFIG_BIGINT_CLASSICAL is not set
# CONFIG_BIGINT_MONTGOMERY is not set
CONFIG_BIGINT_BARRETT=y
CONFIG_BIGINT_CRT=y
# CONFIG_BIGINT_KARATSUBA is not set
MUL_KARATSUBA_THRESH=0
SQU_KARATSUBA_THRESH=0
CONFIG_BIGINT_SLIDING_WINDOW=y
CONFIG_BIGINT_SQUARE=y
# CONFIG_BIGINT_CHECK_ON is not set

121
config/makefile.conf Normal file
View File

@ -0,0 +1,121 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser General Public License
# along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# 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_6_0
CONFIG_VISUAL_STUDIO_6_0_BASE:=$(shell cygpath -w $(CONFIG_VISUAL_STUDIO_6_0_BASE))
CONFIG_VISUAL_STUDIO_6_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_6_0_BASE))
export INCLUDE=$(CONFIG_VISUAL_STUDIO_6_0_BASE)\vc98\Include
export LIB=$(CONFIG_VISUAL_STUDIO_6_0_BASE)\vc98\Lib
PATH:=$(CONFIG_VISUAL_STUDIO_6_0_BASE_UNIX)/common/msdev98/bin:$(CONFIG_VISUAL_STUDIO_6_0_BASE_UNIX)/vc98/bin:$(PATH)
else
ifdef CONFIG_VISUAL_STUDIO_7_0
CONFIG_VISUAL_STUDIO_7_0_BASE:=$(shell cygpath -w $(CONFIG_VISUAL_STUDIO_7_0_BASE))
CONFIG_VISUAL_STUDIO_7_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_7_0_BASE))
export INCLUDE=$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\include;$(CONFIG_VISUAL_STUDIO_7_0_BASE)\vc7\platformsdk\include
export LIB=$(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)
else
ifdef CONFIG_VISUAL_STUDIO_8_0
CONFIG_VISUAL_STUDIO_8_0_BASE:=$(shell cygpath -w $(CONFIG_VISUAL_STUDIO_8_0_BASE))
CONFIG_VISUAL_STUDIO_8_0_BASE_UNIX:=$(shell cygpath -u $(CONFIG_VISUAL_STUDIO_8_0_BASE))
export INCLUDE=$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\include;$(CONFIG_VISUAL_STUDIO_8_0_BASE)\vc\platformsdk\include
export LIB=$(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
endif
endif
CC=cl.exe
LD=link.exe
CFLAGS+=/nologo /W3 /D "WIN32" /D "_MBCS" /D "_CONSOLE" /FD /I"..\ssl" /I"..\config" /c
#CFLAGS+=/nologo /W3 /D "WIN32" /D "_MBCS" /D "_CONSOLE" /FD /I"..\ssl" /I"..\config" /D "_CRT_SECURE_NO_DEPRECATE" /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../config
LD=$(CC)
# 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
CFLAGS += -fPIC
# Cygwin
else
CFLAGS += -DCONFIG_PLATFORM_CYGWIN
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*

View File

@ -0,0 +1,53 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser 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
#
ifneq ($(MAKECMDGOALS), clean)
ifdef CONFIG_PLATFORM_WIN32
GO_DOT_NET=y
endif
ifdef CONFIG_PLATFORM_CYGWIN
GO_DOT_NET=y
endif
ifdef GO_DOT_NET
all: test_dot_net_location
# find out where the C# compiler is
CONFIG_DOT_NET_FRAMEWORK_BASE:=$(shell cygpath -u $(CONFIG_DOT_NET_FRAMEWORK_BASE))
test_dot_net_location:
@if ! [ -d "$(CONFIG_DOT_NET_FRAMEWORK_BASE)" ]; then \
echo "*** Error: .NET path of $(CONFIG_DOT_NET_FRAMEWORK_BASE) doesn't exist" && exit 1; \
fi
PATH:=$(CONFIG_DOT_NET_FRAMEWORK_BASE):$(PATH)
else # Linux?
all: test_mcs
test_mcs:
@if ! mcs --about > /dev/null 2>&1; then \
echo "Mono not installed! - go " \
"to http://www.mono-project.com/Main_Page" && exit 1; \
fi
endif # Linux
endif # not 'clean'

56
config/makefile.java.conf Normal file
View File

@ -0,0 +1,56 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser 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
#
ifneq ($(MAKECMDGOALS), clean)
all: test_jdk_location
test_jdk_location:
@if ! [ -d "$(CONFIG_JAVA_HOME)" ]; then \
echo "*** Error: JDK path of $(CONFIG_JAVA_HOME) doesn't exist" && exit 1; \
fi
ifdef CONFIG_PLATFORM_CYGWIN
CONFIG_JAVA_HOME:=$(shell cygpath -u $(CONFIG_JAVA_HOME))
CFLAGS += -I"$(CONFIG_JAVA_HOME)/include"
CFLAGS += -I"$(CONFIG_JAVA_HOME)/include/win32"
JAVA_BIN:=$(CONFIG_JAVA_HOME)/bin
else
ifdef CONFIG_PLATFORM_WIN32
CONFIG_JAVA_HOME:=$(shell cygpath -w $(CONFIG_JAVA_HOME))
CFLAGS += /I"$(CONFIG_JAVA_HOME)\include"
CFLAGS += /I"$(CONFIG_JAVA_HOME)\include\win32"
JAVA_BIN:=$(shell cygpath -u $(CONFIG_JAVA_HOME)\bin)
else # Linux
CFLAGS += -I$(CONFIG_JAVA_HOME)/include
ifdef CONFIG_PLATFORM_SOLARIS
CFLAGS += -I$(CONFIG_JAVA_HOME)/include/solaris
else
CFLAGS += -I$(CONFIG_JAVA_HOME)/include/linux
endif
JAVA_BIN:=$(CONFIG_JAVA_HOME)/bin
endif
endif
PATH:=$(JAVA_BIN):$(PATH)
endif # not 'clean'

19
config/makefile.post Normal file
View File

@ -0,0 +1,19 @@
ifneq ($(MAKECMDGOALS), clean)
ifndef CONFIG_PLATFORM_WIN32
ifndef CONFIG_PLATFORM_SOLARIS
# do dependencies
-include .depend
all : .depend
.depend: $(wildcard *.c)
@$(CC) $(CFLAGS) -MM $^ > $@
endif # 'not' solaris
endif # 'not' win32
ifdef CONFIG_PLATFORM_WIN32
OBJ:=$(OBJ:.o=.obj)
%.obj : %.c
$(CC) $(CFLAGS) $<
endif # win32
endif # end of 'not' clean

View File

@ -0,0 +1,255 @@
Introduction
------------
The configuration database is collection of configuration options
organized in a tree structure:
+- Code maturity level options
| +- Prompt for development and/or incomplete code/drivers
+- General setup
| +- Networking support
| +- System V IPC
| +- BSD Process Accounting
| +- Sysctl support
+- Loadable module support
| +- Enable loadable module support
| +- Set version information on all module symbols
| +- Kernel module loader
+- ...
Every entry has its own dependencies. These dependencies are used
to determine the visible of an entry. Any child entry is only
visible if its parent entry is also visible.
Menu entries
------------
Most entries define a config option, all other entries help to organize
them. A single configuration option is defined like this:
config MODVERSIONS
bool "Set version information on all module symbols"
depends MODULES
help
Usually, modules have to be recompiled whenever you switch to a new
kernel. ...
Every line starts with a key word and can be followed by multiple
arguments. "config" starts a new config entry. The following lines
define attributes for this config option. Attributes can be the type of
the config option, input prompt, dependencies, help text and default
values. A config option can be defined multiple times with the same
name, but every definition can have only a single input prompt and the
type must not conflict.
Menu attributes
---------------
A menu entry can have a number of attributes. Not all of them are
applicable everywhere (see syntax).
- type definition: "bool"/"tristate"/"string"/"hex"/"integer"
Every config option must have a type. There are only two basic types:
tristate and string, the other types base on these two. The type
definition optionally accepts an input prompt, so these two examples
are equivalent:
bool "Networking support"
and
bool
prompt "Networking support"
- input prompt: "prompt" <prompt> ["if" <expr>]
Every menu entry can have at most one prompt, which is used to display
to the user. Optionally dependencies only for this prompt can be added
with "if".
- default value: "default" <symbol> ["if" <expr>]
A config option can have any number of default values. If multiple
default values are visible, only the first defined one is active.
Default values are not limited to the menu entry, where they are
defined, this means the default can be defined somewhere else or be
overriden by an earlier definition.
The default value is only assigned to the config symbol if no other
value was set by the user (via the input prompt above). If an input
prompt is visible the default value is presented to the user and can
be overridden by him.
Optionally dependencies only for this default value can be added with
"if".
- dependencies: "depends on"/"requires" <expr>
This defines a dependency for this menu entry. If multiple
dependencies are defined they are connected with '&&'. Dependencies
are applied to all other options within this menu entry (which also
accept "if" expression), so these two examples are equivalent:
bool "foo" if BAR
default y if BAR
and
depends on BAR
bool "foo"
default y
- help text: "help"
This defines a help text. The end of the help text is determined by
the level indentation, this means it ends at the first line which has
a smaller indentation than the first line of the help text.
Menu dependencies
-----------------
Dependencies define the visibility of a menu entry and can also reduce
the input range of tristate symbols. The tristate logic used in the
expressions uses one more state than normal boolean logic to express the
module state. Dependency expressions have the following syntax:
<expr> ::= <symbol> (1)
<symbol> '=' <symbol> (2)
<symbol> '!=' <symbol> (3)
'(' <expr> ')' (4)
'!' <expr> (5)
<expr> '||' <expr> (6)
<expr> '&&' <expr> (7)
Expressions are listed in decreasing order of precedence.
(1) Convert the symbol into an expression. Boolean and tristate symbols
are simply converted into the respective expression values. All
other symbol types result in 'n'.
(2) If the values of both symbols are equal, it returns 'y',
otherwise 'n'.
(3) If the values of both symbols are equal, it returns 'n',
otherwise 'y'.
(4) Returns the value of the expression. Used to override precedence.
(5) Returns the result of (2-/expr/).
(6) Returns the result of min(/expr/, /expr/).
(7) Returns the result of max(/expr/, /expr/).
An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2
respectively for calculations). A menu entry becomes visible when it's
expression evaluates to 'm' or 'y'.
There are two type of symbols: constant and nonconstant symbols.
Nonconstant symbols are the most common ones and are defined with the
'config' statement. Nonconstant symbols consist entirely of alphanumeric
characters or underscores.
Constant symbols are only part of expressions. Constant symbols are
always surrounded by single or double quotes. Within the quote any
other character is allowed and the quotes can be escaped using '\'.
Menu structure
--------------
The position of a menu entry in the tree is determined in two ways. First
it can be specified explicitely:
menu "Network device support"
depends NET
config NETDEVICES
...
endmenu
All entries within the "menu" ... "endmenu" block become a submenu of
"Network device support". All subentries inherit the dependencies from
the menu entry, e.g. this means the dependency "NET" is added to the
dependency list of the config option NETDEVICES.
The other way to generate the menu structure is done by analyzing the
dependencies. If a menu entry somehow depends on the previous entry, it
can be made a submenu of it. First the the previous (parent) symbol must
be part of the dependency list and then one of these two condititions
must be true:
- the child entry must become invisible, if the parent is set to 'n'
- the child entry must only be visible, if the parent is visible
config MODULES
bool "Enable loadable module support"
config MODVERSIONS
bool "Set version information on all module symbols"
depends MODULES
comment "module support disabled"
depends !MODULES
MODVERSIONS directly depends on MODULES, this means it's only visible if
MODULES is different from 'n'. The comment on the other hand is always
visible when MODULES it's visible (the (empty) dependency of MODULES is
also part of the comment dependencies).
Kconfig syntax
--------------
The configuration file describes a series of menu entries, where every
line starts with a keyword (except help texts). The following keywords
end a menu entry:
- config
- choice/endchoice
- comment
- menu/endmenu
- if/endif
- source
The first four also start the definition of a menu entry.
config:
"config" <symbol>
<config options>
This defines a config symbol <symbol> and accepts any of above
attributes as options.
choices:
"choice"
<choice options>
<choice block>
"endchoice"
This defines a choice group and accepts any of above attributes as
options. A choice can only be of type bool or tristate, while a boolean
choice only allows a single config entry to be selected, a tristate
choice also allows any number of config entries to be set to 'm'. This
can be used if multiple drivers for a single hardware exists and only a
single driver can be compiled/loaded into the kernel, but all drivers
can be compiled as modules.
A choice accepts another option "optional", which allows to set the
choice to 'n' and no entry needs to be selected.
comment:
"comment" <prompt>
<comment options>
This defines a comment which is displayed to the user during the
configuration process and is also echoed to the output files. The only
possible options are dependencies.
menu:
"menu" <prompt>
<menu options>
<menu block>
"endmenu"
This defines a menu block, see "Menu structure" above for more
information. The only possible options are dependencies.
if:
"if" <expr>
<if block>
"endif"
This defines an if block. The dependency expression <expr> is appended
to all enclosed menu entries.
source:
"source" <prompt>
This reads the specified configuration file. This file is always parsed.

View File

@ -0,0 +1,121 @@
# Makefile for axTLS
#
# Copyright (C) 2002 Erik Andersen <andersen@codepoet.org>
top_srcdir=../..
top_builddir=../..
srcdir=$(top_srcdir)/scripts/config
include $(top_srcdir)/Rules.mak
all: ncurses conf mconf
ifeq ($(shell uname),SunOS)
LIBS = -lcurses
else
LIBS = -lncurses
endif
ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
else
ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
else
ifeq (/usr/local/include/ncurses/ncurses.h, $(wildcard /usr/local/include/ncurses/ncurses.h))
HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses.h>"
else
ifeq (/usr/local/include/ncurses/curses.h, $(wildcard /usr/local/include/ncurses/curses.h))
HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
else
ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
HOSTNCURSES += -DCURSES_LOC="<ncurses.h>"
else
HOSTNCURSES += -DCURSES_LOC="<curses.h>"
endif
endif
endif
endif
endif
CONF_SRC = conf.c
MCONF_SRC = mconf.c
LXD_SRC = lxdialog/checklist.c lxdialog/menubox.c lxdialog/textbox.c \
lxdialog/yesno.c lxdialog/inputbox.c lxdialog/util.c \
lxdialog/msgbox.c
SHARED_SRC = zconf.tab.c
SHARED_DEPS := $(srcdir)/lkc.h $(srcdir)/lkc_proto.h \
lkc_defs.h $(srcdir)/expr.h zconf.tab.h
CONF_OBJS = $(patsubst %.c,%.o, $(CONF_SRC))
MCONF_OBJS = $(patsubst %.c,%.o, $(MCONF_SRC) $(LXD_SRC))
SHARED_OBJS = $(patsubst %.c,%.o, $(SHARED_SRC))
conf: $(CONF_OBJS) $(SHARED_OBJS)
$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@
mconf: $(MCONF_OBJS) $(SHARED_OBJS)
$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@ $(LIBS)
$(CONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
$(HOSTCC) $(HOSTCFLAGS) -I. -c $< -o $@
$(MCONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
@[ -d $(@D) ] || mkdir -v $(@D)
$(HOSTCC) $(HOSTCFLAGS) $(HOSTNCURSES) -I. -c $< -o $@
lkc_defs.h: $(srcdir)/lkc_proto.h
@sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
###
# The following requires flex/bison
# By default we use the _shipped versions, uncomment the
# following line if you are modifying the flex/bison src.
#LKC_GENPARSER := 1
ifdef LKC_GENPARSER
%.tab.c %.tab.h: $(srcdir)/%.y
bison -t -d -v -b $* -p $(notdir $*) $<
lex.%.c: $(srcdir)/%.l
flex -P$(notdir $*) -o$@ $<
else
lex.zconf.o: lex.zconf.c $(SHARED_DEPS)
$(HOSTCC) $(HOSTCFLAGS) -I$(srcdir) -c $< -o $@
lex.zconf.c: $(srcdir)/lex.zconf.c_shipped
cp $< $@
zconf.tab.c: $(srcdir)/zconf.tab.c_shipped
cp $< $@
zconf.tab.h: $(srcdir)/zconf.tab.h_shipped
cp $< $@
endif
zconf.tab.o: zconf.tab.c lex.zconf.c $(srcdir)/confdata.c $(srcdir)/expr.c \
$(srcdir)/symbol.c $(srcdir)/menu.c $(SHARED_DEPS)
$(HOSTCC) $(HOSTCFLAGS) -I$(srcdir) -I. -c $< -o $@
.PHONY: ncurses
ncurses:
@echo "main() {}" > lxtemp.c
@if $(HOSTCC) lxtemp.c $(LIBS) ; then \
rm -f lxtemp.c a.out; \
else \
rm -f lxtemp.c; \
echo -e "\007" ;\
echo ">> Unable to find the Ncurses libraries." ;\
echo ">>" ;\
echo ">> You must have Ncurses installed in order" ;\
echo ">> to use 'make menuconfig'" ;\
echo ;\
exit 1 ;\
fi
clean:
rm -f *.o *~ ../../*~ core *.exe $(TARGETS) $(MCONF_OBJS) $(CONF_OBJS)
rm -f conf conf.exe mconf mconf.exe zconf.tab.c zconf.tab.h lex.zconf.c lkc_defs.h
rm -f ../..config.h

View File

@ -0,0 +1,583 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
static void conf(struct menu *menu);
static void check_conf(struct menu *menu);
enum {
ask_all,
ask_new,
ask_silent,
set_default,
set_yes,
set_mod,
set_no,
set_random
} input_mode = ask_all;
char *defconfig_file;
static int indent = 1;
static int valid_stdin = 1;
static int conf_cnt;
static char line[128];
static struct menu *rootEntry;
static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
static void strip(char *str)
{
char *p = str;
int l;
while ((isspace(*p)))
p++;
l = strlen(p);
if (p != str)
memmove(str, p, l + 1);
if (!l)
return;
p = str + l - 1;
while ((isspace(*p)))
*p-- = 0;
}
static void check_stdin(void)
{
if (!valid_stdin && input_mode == ask_silent) {
printf("aborted!\n\n");
printf("Console input/output is redirected. ");
printf("Run 'make oldconfig' to update configuration.\n\n");
exit(1);
}
}
static void conf_askvalue(struct symbol *sym, const char *def)
{
enum symbol_type type = sym_get_type(sym);
tristate val;
if (!sym_has_value(sym))
printf("(NEW) ");
line[0] = '\n';
line[1] = 0;
if (!sym_is_changable(sym)) {
printf("%s\n", def);
line[0] = '\n';
line[1] = 0;
return;
}
switch (input_mode) {
case ask_new:
case ask_silent:
if (sym_has_value(sym)) {
printf("%s\n", def);
return;
}
check_stdin();
case ask_all:
fflush(stdout);
fgets(line, 128, stdin);
return;
case set_default:
printf("%s\n", def);
return;
default:
break;
}
switch (type) {
case S_INT:
case S_HEX:
case S_STRING:
printf("%s\n", def);
return;
default:
;
}
switch (input_mode) {
case set_yes:
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
case set_mod:
if (type == S_TRISTATE) {
if (sym_tristate_within_range(sym, mod)) {
line[0] = 'm';
line[1] = '\n';
line[2] = 0;
break;
}
} else {
if (sym_tristate_within_range(sym, yes)) {
line[0] = 'y';
line[1] = '\n';
line[2] = 0;
break;
}
}
case set_no:
if (sym_tristate_within_range(sym, no)) {
line[0] = 'n';
line[1] = '\n';
line[2] = 0;
break;
}
case set_random:
do {
val = (tristate)(random() % 3);
} while (!sym_tristate_within_range(sym, val));
switch (val) {
case no: line[0] = 'n'; break;
case mod: line[0] = 'm'; break;
case yes: line[0] = 'y'; break;
}
line[1] = '\n';
line[2] = 0;
break;
default:
break;
}
printf("%s", line);
}
int conf_string(struct menu *menu)
{
struct symbol *sym = menu->sym;
const char *def, *help;
while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text);
printf("(%s) ", sym->name);
def = sym_get_string_value(sym);
if (sym_get_string_value(sym))
printf("[%s] ", def);
conf_askvalue(sym, def);
switch (line[0]) {
case '\n':
break;
case '?':
/* print help */
if (line[1] == '\n') {
help = nohelp_text;
if (menu->sym->help)
help = menu->sym->help;
printf("\n%s\n", menu->sym->help);
def = NULL;
break;
}
default:
line[strlen(line)-1] = 0;
def = line;
}
if (def && sym_set_string_value(sym, def))
return 0;
}
}
static int conf_sym(struct menu *menu)
{
struct symbol *sym = menu->sym;
int type;
tristate oldval, newval;
const char *help;
while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text);
if (sym->name)
printf("(%s) ", sym->name);
type = sym_get_type(sym);
putchar('[');
oldval = sym_get_tristate_value(sym);
switch (oldval) {
case no:
putchar('N');
break;
case mod:
putchar('M');
break;
case yes:
putchar('Y');
break;
}
if (oldval != no && sym_tristate_within_range(sym, no))
printf("/n");
if (oldval != mod && sym_tristate_within_range(sym, mod))
printf("/m");
if (oldval != yes && sym_tristate_within_range(sym, yes))
printf("/y");
if (sym->help)
printf("/?");
printf("] ");
conf_askvalue(sym, sym_get_string_value(sym));
strip(line);
switch (line[0]) {
case 'n':
case 'N':
newval = no;
if (!line[1] || !strcmp(&line[1], "o"))
break;
continue;
case 'm':
case 'M':
newval = mod;
if (!line[1])
break;
continue;
case 'y':
case 'Y':
newval = yes;
if (!line[1] || !strcmp(&line[1], "es"))
break;
continue;
case 0:
newval = oldval;
break;
case '?':
goto help;
default:
continue;
}
if (sym_set_tristate_value(sym, newval))
return 0;
help:
help = nohelp_text;
if (sym->help)
help = sym->help;
printf("\n%s\n", help);
}
}
static int conf_choice(struct menu *menu)
{
struct symbol *sym, *def_sym;
struct menu *child;
int type;
bool is_new;
sym = menu->sym;
type = sym_get_type(sym);
is_new = !sym_has_value(sym);
if (sym_is_changable(sym)) {
conf_sym(menu);
sym_calc_value(sym);
switch (sym_get_tristate_value(sym)) {
case no:
return 1;
case mod:
return 0;
case yes:
break;
}
} else {
switch (sym_get_tristate_value(sym)) {
case no:
return 1;
case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
case yes:
break;
}
}
while (1) {
int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
line[0] = '0';
line[1] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
if (!child->sym) {
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue;
}
cnt++;
if (child->sym == def_sym) {
def = cnt;
printf("%*c", indent, '>');
} else
printf("%*c", indent, ' ');
printf(" %d. %s", cnt, menu_get_prompt(child));
if (child->sym->name)
printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym))
printf(" (NEW)");
printf("\n");
}
printf("%*schoice", indent - 1, "");
if (cnt == 1) {
printf("[1]: 1\n");
goto conf_childs;
}
printf("[1-%d", cnt);
if (sym->help)
printf("?");
printf("]: ");
switch (input_mode) {
case ask_new:
case ask_silent:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
case ask_all:
fflush(stdout);
fgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ?
menu->sym->help : nohelp_text);
continue;
}
if (!line[0])
cnt = def;
else if (isdigit(line[0]))
cnt = atoi(line);
else
continue;
break;
case set_random:
def = (random() % cnt) + 1;
case set_default:
case set_yes:
case set_mod:
case set_no:
cnt = def;
printf("%d\n", cnt);
break;
}
conf_childs:
for (child = menu->list; child; child = child->next) {
if (!child->sym || !menu_is_visible(child))
continue;
if (!--cnt)
break;
}
if (!child)
continue;
if (line[strlen(line) - 1] == '?') {
printf("\n%s\n", child->sym->help ?
child->sym->help : nohelp_text);
continue;
}
sym_set_choice_value(sym, child->sym);
if (child->list) {
indent += 2;
conf(child->list);
indent -= 2;
}
return 1;
}
}
static void conf(struct menu *menu)
{
struct symbol *sym;
struct property *prop;
struct menu *child;
if (!menu_is_visible(menu))
return;
sym = menu->sym;
prop = menu->prompt;
if (prop) {
const char *prompt;
switch (prop->type) {
case P_MENU:
if (input_mode == ask_silent && rootEntry != menu) {
check_conf(menu);
return;
}
case P_COMMENT:
prompt = menu_get_prompt(menu);
if (prompt)
printf("%*c\n%*c %s\n%*c\n",
indent, '*',
indent, '*', prompt,
indent, '*');
default:
;
}
}
if (!sym)
goto conf_childs;
if (sym_is_choice(sym)) {
conf_choice(menu);
if (sym->curr.tri != mod)
return;
goto conf_childs;
}
switch (sym->type) {
case S_INT:
case S_HEX:
case S_STRING:
conf_string(menu);
break;
default:
conf_sym(menu);
break;
}
conf_childs:
if (sym)
indent += 2;
for (child = menu->list; child; child = child->next)
conf(child);
if (sym)
indent -= 2;
}
static void check_conf(struct menu *menu)
{
struct symbol *sym;
struct menu *child;
if (!menu_is_visible(menu))
return;
sym = menu->sym;
if (sym) {
if (sym_is_changable(sym) && !sym_has_value(sym)) {
if (!conf_cnt++)
printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
return;
}
for (child = menu->list; child; child = child->next)
check_conf(child);
}
int main(int ac, char **av)
{
int i = 1;
const char *name;
struct stat tmpstat;
if (ac > i && av[i][0] == '-') {
switch (av[i++][1]) {
case 'o':
input_mode = ask_new;
break;
case 's':
input_mode = ask_silent;
valid_stdin = isatty(0) && isatty(1) && isatty(2);
break;
case 'd':
input_mode = set_default;
break;
case 'D':
input_mode = set_default;
defconfig_file = av[i++];
if (!defconfig_file) {
printf("%s: No default config file specified\n",
av[0]);
exit(1);
}
break;
case 'n':
input_mode = set_no;
break;
case 'm':
input_mode = set_mod;
break;
case 'y':
input_mode = set_yes;
break;
case 'r':
input_mode = set_random;
srandom(time(NULL));
break;
case 'h':
case '?':
printf("%s [-o|-s] config\n", av[0]);
exit(0);
}
}
name = av[i];
if (!name) {
printf("%s: configuration file missing\n", av[0]);
}
conf_parse(name);
//zconfdump(stdout);
switch (input_mode) {
case set_default:
if (!defconfig_file)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
printf("***\n"
"*** Can't find default configuration \"%s\"!\n"
"***\n", defconfig_file);
exit(1);
}
break;
case ask_silent:
if (stat(".config", &tmpstat)) {
printf("***\n"
"*** You have not yet configured axTLS!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make config\").\n"
"***\n");
exit(1);
}
case ask_all:
case ask_new:
conf_read(NULL);
break;
default:
break;
}
if (input_mode != ask_silent) {
rootEntry = &rootmenu;
conf(&rootmenu);
if (input_mode == ask_all) {
input_mode = ask_silent;
valid_stdin = 1;
}
}
do {
conf_cnt = 0;
check_conf(&rootmenu);
} while (conf_cnt);
if (conf_write(NULL)) {
fprintf(stderr, "\n*** Error during writing of the axTLS configuration.\n\n");
return 1;
}
return 0;
}

View File

@ -0,0 +1,458 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
const char conf_def_filename[] = "config/.config";
const char conf_defname[] = "config/defconfig";
const char *conf_confnames[] = {
"config/.config",
conf_defname,
NULL,
};
static char *conf_expand_value(const char *in)
{
struct symbol *sym;
const char *src;
static char res_value[SYMBOL_MAXLENGTH];
char *dst, name[SYMBOL_MAXLENGTH];
res_value[0] = 0;
dst = name;
while ((src = strchr(in, '$'))) {
strncat(res_value, in, src - in);
src++;
dst = name;
while (isalnum(*src) || *src == '_')
*dst++ = *src++;
*dst = 0;
sym = sym_lookup(name, 0);
sym_calc_value(sym);
strcat(res_value, sym_get_string_value(sym));
in = src;
}
strcat(res_value, in);
return res_value;
}
char *conf_get_default_confname(void)
{
struct stat buf;
static char fullname[PATH_MAX+1];
char *env, *name;
name = conf_expand_value(conf_defname);
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
if (!stat(fullname, &buf))
return fullname;
}
return name;
}
int conf_read(const char *name)
{
FILE *in = NULL;
char line[1024];
char *p, *p2;
int lineno = 0;
struct symbol *sym;
struct property *prop;
struct expr *e;
int i;
if (name) {
in = zconf_fopen(name);
} else {
const char **names = conf_confnames;
while ((name = *names++)) {
name = conf_expand_value(name);
in = zconf_fopen(name);
if (in) {
printf("#\n"
"# using defaults found in %s\n"
"#\n", name);
break;
}
}
}
if (!in)
return 1;
for_all_symbols(i, sym) {
sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
sym->flags &= ~SYMBOL_VALID;
switch (sym->type) {
case S_INT:
case S_HEX:
case S_STRING:
if (sym->user.val)
free(sym->user.val);
default:
sym->user.val = NULL;
sym->user.tri = no;
}
}
while (fgets(line, sizeof(line), in)) {
lineno++;
sym = NULL;
switch (line[0]) {
case '#':
if (line[1]!=' ')
continue;
p = strchr(line + 2, ' ');
if (!p)
continue;
*p++ = 0;
if (strncmp(p, "is not set", 10))
continue;
sym = sym_find(line + 2);
if (!sym) {
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
break;
}
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW;
break;
default:
;
}
break;
case 'A' ... 'Z':
p = strchr(line, '=');
if (!p)
continue;
*p++ = 0;
p2 = strchr(p, '\n');
if (p2)
*p2 = 0;
sym = sym_find(line);
if (!sym) {
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
break;
}
switch (sym->type) {
case S_TRISTATE:
if (p[0] == 'm') {
sym->user.tri = mod;
sym->flags &= ~SYMBOL_NEW;
break;
}
case S_BOOLEAN:
if (p[0] == 'y') {
sym->user.tri = yes;
sym->flags &= ~SYMBOL_NEW;
break;
}
if (p[0] == 'n') {
sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW;
break;
}
break;
case S_STRING:
if (*p++ != '"')
break;
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
if (*p2 == '"') {
*p2 = 0;
break;
}
memmove(p2, p2 + 1, strlen(p2));
}
if (!p2) {
fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
exit(1);
}
case S_INT:
case S_HEX:
if (sym_string_valid(sym, p)) {
sym->user.val = strdup(p);
sym->flags &= ~SYMBOL_NEW;
} else {
fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
exit(1);
}
break;
default:
;
}
break;
case '\n':
break;
default:
continue;
}
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->user.tri) {
case no:
break;
case mod:
if (cs->user.tri == yes)
/* warn? */;
break;
case yes:
if (cs->user.tri != no)
/* warn? */;
cs->user.val = sym;
break;
}
cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
cs->flags &= ~SYMBOL_NEW;
}
}
fclose(in);
if (modules_sym)
sym_calc_value(modules_sym);
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
if (sym->visible == no)
sym->flags |= SYMBOL_NEW;
switch (sym->type) {
case S_STRING:
case S_INT:
case S_HEX:
if (!sym_string_within_range(sym, sym->user.val))
sym->flags |= SYMBOL_NEW;
default:
break;
}
}
if (!sym_is_choice(sym))
continue;
prop = sym_get_choice_prop(sym);
for (e = prop->expr; e; e = e->left.expr)
if (e->right.sym->visible != no)
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
}
sym_change_count = 1;
return 0;
}
struct menu *next_menu(struct menu *menu)
{
if (menu->list) return menu->list;
do {
if (menu->next) {
menu = menu->next;
break;
}
} while ((menu = menu->parent));
return menu;
}
#define SYMBOL_FORCEWRITE (1<<31)
int conf_write(const char *name)
{
FILE *out, *out_h;
struct symbol *sym;
struct menu *menu;
const char *basename;
char dirname[128], tmpname[128], newname[128];
int type, l;
const char *str;
dirname[0] = 0;
if (name && name[0]) {
struct stat st;
char *slash;
if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
strcpy(dirname, name);
strcat(dirname, "/");
basename = conf_def_filename;
} else if ((slash = strrchr(name, '/'))) {
int size = slash - name + 1;
memcpy(dirname, name, size);
dirname[size] = 0;
if (slash[1])
basename = slash + 1;
else
basename = conf_def_filename;
} else
basename = name;
} else
basename = conf_def_filename;
sprintf(newname, "config/%s.tmpconfig.%d", dirname, (int)getpid());
out = fopen(newname, "w");
if (!out)
return 1;
out_h = NULL;
if (!name) {
out_h = fopen("config/.tmpconfig.h", "w");
if (!out_h)
return 1;
}
fprintf(out, "#\n"
"# Automatically generated make config: don't edit\n"
"#\n");
if (out_h) {
fprintf(out_h, "/*\n"
" * Automatically generated header file: don't edit\n"
" */\n\n");
#if 0
"/* Version Number */\n"
"#define BB_VER \"%s\"\n"
"#define BB_BT \"%s\"\n",
getenv("VERSION"),
getenv("BUILDTIME"));
if (getenv("EXTRA_VERSION"))
fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
getenv("EXTRA_VERSION"));
fprintf(out_h, "\n");
#endif
}
if (!sym_change_count)
sym_clear_all_valid();
/* Force write of all non-duplicate symbols. */
/* Write out everything by default. */
for(menu = rootmenu.list; menu; menu = next_menu(menu))
if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
menu = rootmenu.list;
while (menu) {
sym = menu->sym;
if (!sym) {
if (!menu_is_visible(menu))
goto next;
str = menu_get_prompt(menu);
fprintf(out, "\n"
"#\n"
"# %s\n"
"#\n", str);
if (out_h)
fprintf(out_h, "\n"
"/*\n"
" * %s\n"
" */\n", str);
} else if (!(sym->flags & SYMBOL_CHOICE)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_FORCEWRITE))
goto next;
sym->flags &= ~SYMBOL_FORCEWRITE;
type = sym->type;
if (type == S_TRISTATE) {
sym_calc_value(modules_sym);
if (modules_sym->curr.tri == no)
type = S_BOOLEAN;
}
switch (type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (sym_get_tristate_value(sym)) {
case no:
fprintf(out, "# %s is not set\n", sym->name);
if (out_h)
fprintf(out_h, "#undef %s\n", sym->name);
break;
case mod:
#if 0
fprintf(out, "%s=m\n", sym->name);
if (out_h)
fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
#endif
break;
case yes:
fprintf(out, "%s=y\n", sym->name);
if (out_h)
fprintf(out_h, "#define %s 1\n", sym->name);
break;
}
break;
case S_STRING:
// fix me
str = sym_get_string_value(sym);
fprintf(out, "%s=\"", sym->name);
if (out_h)
fprintf(out_h, "#define %s \"", sym->name);
do {
l = strcspn(str, "\"\\");
if (l) {
fwrite(str, l, 1, out);
if (out_h)
fwrite(str, l, 1, out_h);
}
str += l;
while (*str == '\\' || *str == '"') {
fprintf(out, "\\%c", *str);
if (out_h)
fprintf(out_h, "\\%c", *str);
str++;
}
} while (*str);
fputs("\"\n", out);
if (out_h)
fputs("\"\n", out_h);
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
if (out_h)
fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
break;
}
case S_INT:
str = sym_get_string_value(sym);
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
if (out_h)
fprintf(out_h, "#define %s %s\n", sym->name, str);
break;
}
}
next:
menu = next_menu(menu);
}
fclose(out);
if (out_h) {
fclose(out_h);
rename("config/.tmpconfig.h", "config/config.h");
file_write_dep(NULL);
}
if (!name || basename != conf_def_filename) {
if (!name)
name = conf_def_filename;
sprintf(tmpname, "%s.old", name);
rename(name, tmpname);
}
sprintf(tmpname, "%s%s", dirname, basename);
if (rename(newname, tmpname))
return 1;
sym_change_count = 0;
return 0;
}

1099
config/scripts/config/expr.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#ifndef EXPR_H
#define EXPR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#ifndef __cplusplus
#include <stdbool.h>
#endif
struct file {
struct file *next;
struct file *parent;
char *name;
int lineno;
int flags;
};
#define FILE_BUSY 0x0001
#define FILE_SCANNED 0x0002
#define FILE_PRINTED 0x0004
typedef enum tristate {
no, mod, yes
} tristate;
enum expr_type {
E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
};
union expr_data {
struct expr *expr;
struct symbol *sym;
};
struct expr {
enum expr_type type;
union expr_data left, right;
};
#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define E_NOT(dep) (2-(dep))
struct expr_value {
struct expr *expr;
tristate tri;
};
struct symbol_value {
void *val;
tristate tri;
};
enum symbol_type {
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
};
struct symbol {
struct symbol *next;
char *name;
char *help;
enum symbol_type type;
struct symbol_value curr, user;
tristate visible;
int flags;
struct property *prop;
struct expr *dep, *dep2;
struct expr_value rev_dep;
};
#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#define SYMBOL_YES 0x0001
#define SYMBOL_MOD 0x0002
#define SYMBOL_NO 0x0004
#define SYMBOL_CONST 0x0007
#define SYMBOL_CHECK 0x0008
#define SYMBOL_CHOICE 0x0010
#define SYMBOL_CHOICEVAL 0x0020
#define SYMBOL_PRINTED 0x0040
#define SYMBOL_VALID 0x0080
#define SYMBOL_OPTIONAL 0x0100
#define SYMBOL_WRITE 0x0200
#define SYMBOL_CHANGED 0x0400
#define SYMBOL_NEW 0x0800
#define SYMBOL_AUTO 0x1000
#define SYMBOL_CHECKED 0x2000
#define SYMBOL_CHECK_DONE 0x4000
#define SYMBOL_WARNED 0x8000
#define SYMBOL_MAXLENGTH 256
#define SYMBOL_HASHSIZE 257
#define SYMBOL_HASHMASK 0xff
enum prop_type {
P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
};
struct property {
struct property *next;
struct symbol *sym;
enum prop_type type;
const char *text;
struct expr_value visible;
struct expr *expr;
struct menu *menu;
struct file *file;
int lineno;
};
#define for_all_properties(sym, st, tok) \
for (st = sym->prop; st; st = st->next) \
if (st->type == (tok))
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
#define for_all_prompts(sym, st) \
for (st = sym->prop; st; st = st->next) \
if (st->text)
struct menu {
struct menu *next;
struct menu *parent;
struct menu *list;
struct symbol *sym;
struct property *prompt;
struct expr *dep;
unsigned int flags;
//char *help;
struct file *file;
int lineno;
void *data;
};
#define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002
#ifndef SWIG
extern struct file *file_list;
extern struct file *current_file;
struct file *lookup_file(const char *name);
extern struct symbol symbol_yes, symbol_no, symbol_mod;
extern struct symbol *modules_sym;
extern int cdebug;
struct expr *expr_alloc_symbol(struct symbol *sym);
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(struct expr *org);
void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
tristate expr_calc_value(struct expr *e);
struct expr *expr_eliminate_yn(struct expr *e);
struct expr *expr_trans_bool(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e);
int expr_contains_symbol(struct expr *dep, struct symbol *sym);
bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */
void expr_gstr_print(struct expr *e, struct gstr *gs);
static inline int expr_is_yes(struct expr *e)
{
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
}
static inline int expr_is_no(struct expr *e)
{
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* EXPR_H */

File diff suppressed because it is too large Load Diff

123
config/scripts/config/lkc.h Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#ifndef LKC_H
#define LKC_H
#include "expr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LKC_DIRECT_LINK
#define P(name,type,arg) extern type name arg
#else
#include "lkc_defs.h"
#define P(name,type,arg) extern type (*name ## _p) arg
#endif
#include "lkc_proto.h"
#undef P
#define SRCTREE "srctree"
int zconfparse(void);
void zconfdump(FILE *out);
extern int zconfdebug;
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
void zconf_nextfile(const char *name);
int zconf_lineno(void);
char *zconf_curname(void);
/* confdata.c */
extern const char conf_def_filename[];
extern char conf_filename[];
char *conf_get_default_confname(void);
/* kconfig_load.c */
void kconfig_load(void);
/* menu.c */
void menu_init(void);
void menu_add_menu(void);
void menu_end_menu(void);
void menu_add_entry(struct symbol *sym);
void menu_end_entry(void);
void menu_add_dep(struct expr *dep);
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
void menu_finalize(struct menu *parent);
void menu_set_type(int type);
/* util.c */
struct file *file_lookup(const char *name);
int file_write_dep(const char *name);
struct gstr {
size_t len;
char *s;
};
struct gstr str_new(void);
struct gstr str_assign(const char *s);
void str_free(struct gstr *gs);
void str_append(struct gstr *gs, const char *s);
void str_printf(struct gstr *gs, const char *fmt, ...);
const char *str_get(struct gstr *gs);
/* symbol.c */
void sym_init(void);
void sym_clear_all_valid(void);
void sym_set_changed(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop);
static inline tristate sym_get_tristate_value(struct symbol *sym)
{
return sym->curr.tri;
}
static inline struct symbol *sym_get_choice_value(struct symbol *sym)
{
return (struct symbol *)sym->curr.val;
}
static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
{
return sym_set_tristate_value(chval, yes);
}
static inline bool sym_is_choice(struct symbol *sym)
{
return sym->flags & SYMBOL_CHOICE ? true : false;
}
static inline bool sym_is_choice_value(struct symbol *sym)
{
return sym->flags & SYMBOL_CHOICEVAL ? true : false;
}
static inline bool sym_is_optional(struct symbol *sym)
{
return sym->flags & SYMBOL_OPTIONAL ? true : false;
}
static inline bool sym_has_value(struct symbol *sym)
{
return sym->flags & SYMBOL_NEW ? false : true;
}
#ifdef __cplusplus
}
#endif
#endif /* LKC_H */

View File

@ -0,0 +1,40 @@
/* confdata.c */
P(conf_parse,void,(const char *name));
P(conf_read,int,(const char *name));
P(conf_write,int,(const char *name));
/* menu.c */
P(rootmenu,struct menu,);
P(menu_is_visible,bool,(struct menu *menu));
P(menu_get_prompt,const char *,(struct menu *menu));
P(menu_get_root_menu,struct menu *,(struct menu *menu));
P(menu_get_parent_menu,struct menu *,(struct menu *menu));
/* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
P(sym_change_count,int,);
P(sym_lookup,struct symbol *,(const char *name, int isconst));
P(sym_find,struct symbol *,(const char *name));
P(sym_re_search,struct symbol **,(const char *pattern));
P(sym_type_name,const char *,(enum symbol_type type));
P(sym_calc_value,void,(struct symbol *sym));
P(sym_get_type,enum symbol_type,(struct symbol *sym));
P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
P(sym_is_changable,bool,(struct symbol *sym));
P(sym_get_choice_prop,struct property *,(struct symbol *sym));
P(sym_get_default_prop,struct property *,(struct symbol *sym));
P(sym_get_string_value,const char *,(struct symbol *sym));
P(prop_get_type_name,const char *,(enum prop_type type));
/* expr.c */
P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));

View File

@ -0,0 +1,4 @@
This is NOT the official version of dialog. This version has been
significantly modified from the original. It is for use by the Linux
kernel configuration script. Please do not bother Savio Lam with
questions about this program.

View File

@ -0,0 +1,372 @@
/*
* checklist.c -- implements the checklist box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static int list_width, check_x, item_x, checkflag;
/*
* Print list item
*/
static void
print_item (WINDOW * win, const char *item, int status,
int choice, int selected)
{
int i;
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
for (i = 0; i < list_width; i++)
waddch (win, ' ');
wmove (win, choice, check_x);
wattrset (win, selected ? check_selected_attr : check_attr);
if (checkflag == FLAG_CHECK)
wprintw (win, "[%c]", status ? 'X' : ' ');
else
wprintw (win, "(%c)", status ? 'X' : ' ');
wattrset (win, selected ? tag_selected_attr : tag_attr);
mvwaddch(win, choice, item_x, item[0]);
wattrset (win, selected ? item_selected_attr : item_attr);
waddstr (win, (char *)item+1);
if (selected) {
wmove (win, choice, check_x+1);
wrefresh (win);
}
}
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int choice, int item_no, int scroll,
int y, int x, int height)
{
wmove(win, y, x);
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
}
/*
* Display the termination buttons
*/
static void
print_buttons( WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button (dialog, "Select", y, x, selected == 0);
print_button (dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x+1 + 14*selected);
wrefresh (dialog);
}
/*
* Display a dialog box with a list of options that can be turned on or off
* The `flag' parameter is used to select between radiolist and checklist.
*/
int
dialog_checklist (const char *title, const char *prompt, int height, int width,
int list_height, int item_no, struct dialog_list_item ** items,
int flag)
{
int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
WINDOW *dialog, *list;
checkflag = flag;
/* Allocate space for storing item on/off status */
if ((status = malloc (sizeof (int) * item_no)) == NULL) {
endwin ();
fprintf (stderr,
"\nCan't allocate memory in dialog_checklist().\n");
exit (-1);
}
/* Initializes status */
for (i = 0; i < item_no; i++) {
status[i] = (items[i]->selected == 1); /* ON */
if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */
choice = i + 1;
}
if (choice)
choice--;
max_choice = MIN (list_height, item_no);
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
list_width = width - 6;
box_y = height - list_height - 5;
box_x = (width - list_width) / 2 - 1;
/* create new window for the list */
list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
keypad (list, TRUE);
/* draw a box around the list items */
draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
menubox_border_attr, menubox_attr);
/* Find length of longest item in order to center checklist */
check_x = 0;
for (i = 0; i < item_no; i++)
check_x = MAX (check_x, + strlen (items[i]->name) + 4);
check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
if (choice >= list_height) {
scroll = choice - list_height + 1;
choice -= scroll;
}
/* Print the list */
for (i = 0; i < max_choice; i++) {
print_item (list, items[scroll + i]->name,
status[i+scroll], i, i == choice);
}
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
print_buttons(dialog, height, width, 0);
wnoutrefresh (list);
wnoutrefresh (dialog);
doupdate ();
while (key != ESC) {
key = wgetch (dialog);
for (i = 0; i < max_choice; i++)
if (toupper(key) == toupper(items[scroll + i]->name[0]))
break;
if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-' ) {
if (key == KEY_UP || key == '-') {
if (!choice) {
if (!scroll)
continue;
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
print_item (list, items[scroll]->name,
status[scroll], 0, FALSE);
scrollok (list, TRUE);
wscrl (list, -1);
scrollok (list, FALSE);
}
scroll--;
print_item (list, items[scroll]->name,
status[scroll], 0, TRUE);
wnoutrefresh (list);
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
wrefresh (dialog);
continue; /* wait for another key press */
} else
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
if (scroll + choice >= item_no - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
print_item (list, items[scroll + max_choice - 1]->name,
status[scroll + max_choice - 1],
max_choice - 1, FALSE);
scrollok (list, TRUE);
scroll (list);
scrollok (list, FALSE);
}
scroll++;
print_item (list, items[scroll + max_choice - 1]->name,
status[scroll + max_choice - 1],
max_choice - 1, TRUE);
wnoutrefresh (list);
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
wrefresh (dialog);
continue; /* wait for another key press */
} else
i = choice + 1;
}
if (i != choice) {
/* De-highlight current item */
print_item (list, items[scroll + choice]->name,
status[scroll + choice], choice, FALSE);
/* Highlight new item */
choice = i;
print_item (list, items[scroll + choice]->name,
status[scroll + choice], choice, TRUE);
wnoutrefresh (list);
wrefresh (dialog);
}
continue; /* wait for another key press */
}
switch (key) {
case 'H':
case 'h':
case '?':
for (i = 0; i < item_no; i++)
items[i]->selected = 0;
items[scroll + choice]->selected = 1;
delwin (dialog);
free (status);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case 'S':
case 's':
case ' ':
case '\n':
if (!button) {
if (flag == FLAG_CHECK) {
status[scroll + choice] = !status[scroll + choice];
wmove (list, choice, check_x);
wattrset (list, check_selected_attr);
wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
} else {
if (!status[scroll + choice]) {
for (i = 0; i < item_no; i++)
status[i] = 0;
status[scroll + choice] = 1;
for (i = 0; i < max_choice; i++)
print_item (list, items[scroll + i]->name,
status[scroll + i], i, i == choice);
}
}
wnoutrefresh (list);
wrefresh (dialog);
for (i = 0; i < item_no; i++) {
items[i]->selected = status[i];
}
} else {
for (i = 0; i < item_no; i++)
items[i]->selected = 0;
items[scroll + choice]->selected = 1;
}
delwin (dialog);
free (status);
return button;
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
/* Now, update everything... */
doupdate ();
}
delwin (dialog);
free (status);
return -1; /* ESC pressed */
}

View File

@ -0,0 +1,161 @@
/*
* colors.h -- color attribute definitions
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Default color definitions
*
* *_FG = foreground
* *_BG = background
* *_HL = highlight?
*/
#define SCREEN_FG COLOR_CYAN
#define SCREEN_BG COLOR_BLUE
#define SCREEN_HL TRUE
#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK
#define SHADOW_HL TRUE
#define DIALOG_FG COLOR_BLACK
#define DIALOG_BG COLOR_WHITE
#define DIALOG_HL FALSE
#define TITLE_FG COLOR_YELLOW
#define TITLE_BG COLOR_WHITE
#define TITLE_HL TRUE
#define BORDER_FG COLOR_WHITE
#define BORDER_BG COLOR_WHITE
#define BORDER_HL TRUE
#define BUTTON_ACTIVE_FG COLOR_WHITE
#define BUTTON_ACTIVE_BG COLOR_BLUE
#define BUTTON_ACTIVE_HL TRUE
#define BUTTON_INACTIVE_FG COLOR_BLACK
#define BUTTON_INACTIVE_BG COLOR_WHITE
#define BUTTON_INACTIVE_HL FALSE
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
#define BUTTON_KEY_ACTIVE_HL TRUE
#define BUTTON_KEY_INACTIVE_FG COLOR_RED
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
#define BUTTON_KEY_INACTIVE_HL FALSE
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
#define BUTTON_LABEL_ACTIVE_HL TRUE
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
#define BUTTON_LABEL_INACTIVE_HL TRUE
#define INPUTBOX_FG COLOR_BLACK
#define INPUTBOX_BG COLOR_WHITE
#define INPUTBOX_HL FALSE
#define INPUTBOX_BORDER_FG COLOR_BLACK
#define INPUTBOX_BORDER_BG COLOR_WHITE
#define INPUTBOX_BORDER_HL FALSE
#define SEARCHBOX_FG COLOR_BLACK
#define SEARCHBOX_BG COLOR_WHITE
#define SEARCHBOX_HL FALSE
#define SEARCHBOX_TITLE_FG COLOR_YELLOW
#define SEARCHBOX_TITLE_BG COLOR_WHITE
#define SEARCHBOX_TITLE_HL TRUE
#define SEARCHBOX_BORDER_FG COLOR_WHITE
#define SEARCHBOX_BORDER_BG COLOR_WHITE
#define SEARCHBOX_BORDER_HL TRUE
#define POSITION_INDICATOR_FG COLOR_YELLOW
#define POSITION_INDICATOR_BG COLOR_WHITE
#define POSITION_INDICATOR_HL TRUE
#define MENUBOX_FG COLOR_BLACK
#define MENUBOX_BG COLOR_WHITE
#define MENUBOX_HL FALSE
#define MENUBOX_BORDER_FG COLOR_WHITE
#define MENUBOX_BORDER_BG COLOR_WHITE
#define MENUBOX_BORDER_HL TRUE
#define ITEM_FG COLOR_BLACK
#define ITEM_BG COLOR_WHITE
#define ITEM_HL FALSE
#define ITEM_SELECTED_FG COLOR_WHITE
#define ITEM_SELECTED_BG COLOR_BLUE
#define ITEM_SELECTED_HL TRUE
#define TAG_FG COLOR_YELLOW
#define TAG_BG COLOR_WHITE
#define TAG_HL TRUE
#define TAG_SELECTED_FG COLOR_YELLOW
#define TAG_SELECTED_BG COLOR_BLUE
#define TAG_SELECTED_HL TRUE
#define TAG_KEY_FG COLOR_YELLOW
#define TAG_KEY_BG COLOR_WHITE
#define TAG_KEY_HL TRUE
#define TAG_KEY_SELECTED_FG COLOR_YELLOW
#define TAG_KEY_SELECTED_BG COLOR_BLUE
#define TAG_KEY_SELECTED_HL TRUE
#define CHECK_FG COLOR_BLACK
#define CHECK_BG COLOR_WHITE
#define CHECK_HL FALSE
#define CHECK_SELECTED_FG COLOR_WHITE
#define CHECK_SELECTED_BG COLOR_BLUE
#define CHECK_SELECTED_HL TRUE
#define UARROW_FG COLOR_GREEN
#define UARROW_BG COLOR_WHITE
#define UARROW_HL TRUE
#define DARROW_FG COLOR_GREEN
#define DARROW_BG COLOR_WHITE
#define DARROW_HL TRUE
/* End of default color definitions */
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
#define COLOR_NAME_LEN 10
#define COLOR_COUNT 8
/*
* Global variables
*/
typedef struct {
char name[COLOR_NAME_LEN];
int value;
} color_names_st;
extern color_names_st color_names[];
extern int color_table[][3];

View File

@ -0,0 +1,199 @@
/*
* dialog.h -- common declarations for all dialog modules
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#ifdef CURSES_LOC
#ifdef __sun__
#define CURS_MACROS
#endif
#include CURSES_LOC
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
* background colors are OR'd rather than separately masked. This version
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
* with standard curses. The simplest fix (to make this work with standard
* curses) uses the wbkgdset() function, not used in the original hack.
* Turn it off if we're building with 1.9.9e, since it just confuses things.
*/
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
#define OLD_NCURSES 1
#undef wbkgdset
#define wbkgdset(w,p) /*nothing*/
#else
#define OLD_NCURSES 0
#endif
#define TR(params) _tracef params
#define ESC 27
#define TAB 9
#define MAX_LEN 2048
#define BUF_SIZE (10*1024)
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#ifndef ACS_ULCORNER
#define ACS_ULCORNER '+'
#endif
#ifndef ACS_LLCORNER
#define ACS_LLCORNER '+'
#endif
#ifndef ACS_URCORNER
#define ACS_URCORNER '+'
#endif
#ifndef ACS_LRCORNER
#define ACS_LRCORNER '+'
#endif
#ifndef ACS_HLINE
#define ACS_HLINE '-'
#endif
#ifndef ACS_VLINE
#define ACS_VLINE '|'
#endif
#ifndef ACS_LTEE
#define ACS_LTEE '+'
#endif
#ifndef ACS_RTEE
#define ACS_RTEE '+'
#endif
#ifndef ACS_UARROW
#define ACS_UARROW '^'
#endif
#ifndef ACS_DARROW
#define ACS_DARROW 'v'
#endif
/*
* Attribute names
*/
#define screen_attr attributes[0]
#define shadow_attr attributes[1]
#define dialog_attr attributes[2]
#define title_attr attributes[3]
#define border_attr attributes[4]
#define button_active_attr attributes[5]
#define button_inactive_attr attributes[6]
#define button_key_active_attr attributes[7]
#define button_key_inactive_attr attributes[8]
#define button_label_active_attr attributes[9]
#define button_label_inactive_attr attributes[10]
#define inputbox_attr attributes[11]
#define inputbox_border_attr attributes[12]
#define searchbox_attr attributes[13]
#define searchbox_title_attr attributes[14]
#define searchbox_border_attr attributes[15]
#define position_indicator_attr attributes[16]
#define menubox_attr attributes[17]
#define menubox_border_attr attributes[18]
#define item_attr attributes[19]
#define item_selected_attr attributes[20]
#define tag_attr attributes[21]
#define tag_selected_attr attributes[22]
#define tag_key_attr attributes[23]
#define tag_key_selected_attr attributes[24]
#define check_attr attributes[25]
#define check_selected_attr attributes[26]
#define uarrow_attr attributes[27]
#define darrow_attr attributes[28]
/* number of attributes */
#define ATTRIBUTE_COUNT 29
/*
* Global variables
*/
extern bool use_colors;
extern chtype attributes[];
#endif
extern const char *backtitle;
struct dialog_list_item {
char *name;
int namelen;
char *tag;
int selected; /* Set to 1 by dialog_*() function. */
};
/*
* Function prototypes
*/
void init_dialog (void);
void end_dialog (void);
void dialog_clear (void);
#ifdef CURSES_LOC
void attr_clear (WINDOW * win, int height, int width, chtype attr);
void color_setup (void);
void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
void print_button (WINDOW * win, const char *label, int y, int x, int selected);
void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
chtype border);
void draw_shadow (WINDOW * win, int y, int x, int height, int width);
#endif
int first_alpha (const char *string, const char *exempt);
int dialog_yesno (const char *title, const char *prompt, int height, int width);
int dialog_msgbox (const char *title, const char *prompt, int height,
int width, int pause);
int dialog_textbox (const char *title, const char *file, int height, int width);
int dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *choice, int item_no,
struct dialog_list_item ** items);
int dialog_checklist (const char *title, const char *prompt, int height,
int width, int list_height, int item_no,
struct dialog_list_item ** items, int flag);
extern unsigned char dialog_input_result[];
int dialog_inputbox (const char *title, const char *prompt, int height,
int width, const char *init);
struct dialog_list_item *first_sel_item(int item_no,
struct dialog_list_item ** items);
/*
* This is the base for fictitious keys, which activate
* the buttons.
*
* Mouse-generated keys are the following:
* -- the first 32 are used as numbers, in addition to '0'-'9'
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
*/
#ifdef CURSES_LOC
#define M_EVENT (KEY_MAX+1)
#endif
/*
* The `flag' parameter in checklist is used to select between
* radiolist and checklist
*/
#define FLAG_CHECK 1
#define FLAG_RADIO 0

View File

@ -0,0 +1,240 @@
/*
* inputbox.c -- implements the input box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
unsigned char dialog_input_result[MAX_LEN + 1];
/*
* Print the termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
print_button (dialog, " Ok ", y, x, selected==0);
print_button (dialog, " Help ", y, x + 14, selected==1);
wmove(dialog, y, x+1+14*selected);
wrefresh(dialog);
}
/*
* Display a dialog box for inputing a string
*/
int
dialog_inputbox (const char *title, const char *prompt, int height, int width,
const char *init)
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1;
unsigned char *instr = dialog_input_result;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
/* Draw the input field box */
box_width = width - 6;
getyx (dialog, y, x);
box_y = y + 2;
box_x = (width - box_width) / 2;
draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
border_attr, dialog_attr);
print_buttons(dialog, height, width, 0);
/* Set up the initial value */
wmove (dialog, box_y, box_x);
wattrset (dialog, inputbox_attr);
if (!init)
instr[0] = '\0';
else
strcpy (instr, init);
input_x = strlen (instr);
if (input_x >= box_width) {
scroll = input_x - box_width + 1;
input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else
waddstr (dialog, instr);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
while (key != ESC) {
key = wgetch (dialog);
if (button == -1) { /* Input box selected */
switch (key) {
case TAB:
case KEY_UP:
case KEY_DOWN:
break;
case KEY_LEFT:
continue;
case KEY_RIGHT:
continue;
case KEY_BACKSPACE:
case 127:
if (input_x || scroll) {
wattrset (dialog, inputbox_attr);
if (!input_x) {
scroll = scroll < box_width - 1 ?
0 : scroll - (box_width - 1);
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width; i++)
waddch (dialog, instr[scroll + input_x + i] ?
instr[scroll + input_x + i] : ' ');
input_x = strlen (instr) - scroll;
} else
input_x--;
instr[scroll + input_x] = '\0';
mvwaddch (dialog, box_y, input_x + box_x, ' ');
wmove (dialog, box_y, input_x + box_x);
wrefresh (dialog);
}
continue;
default:
if (key < 0x100 && isprint (key)) {
if (scroll + input_x < MAX_LEN) {
wattrset (dialog, inputbox_attr);
instr[scroll + input_x] = key;
instr[scroll + input_x + 1] = '\0';
if (input_x == box_width - 1) {
scroll++;
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else {
wmove (dialog, box_y, input_x++ + box_x);
waddch (dialog, key);
}
wrefresh (dialog);
} else
flash (); /* Alarm user about overflow */
continue;
}
}
}
switch (key) {
case 'O':
case 'o':
delwin (dialog);
return 0;
case 'H':
case 'h':
delwin (dialog);
return 1;
case KEY_UP:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
case 1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
}
break;
case TAB:
case KEY_DOWN:
case KEY_RIGHT:
switch (button) {
case -1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
case 0:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
}
break;
case ' ':
case '\n':
delwin (dialog);
return (button == -1 ? 0 : button);
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
}
delwin (dialog);
return -1; /* ESC pressed */
}

View File

@ -0,0 +1,438 @@
/*
* menubox.c -- implements the menu box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Changes by Clifford Wolf (god@clifford.at)
*
* [ 1998-06-13 ]
*
* *) A bugfix for the Page-Down problem
*
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at
* it).
*
* *) Formerly if I selected something my scrolling would be broken because
* lxdialog is re-invoked by the Menuconfig shell script, can't
* remember the last scrolling position, and just sets it so that the
* cursor is at the bottom of the box. Now it writes the temporary file
* lxdialog.scrltmp which contains this information. The file is
* deleted by lxdialog if the user leaves a submenu or enters a new
* one, but it would be nice if Menuconfig could make another "rm -f"
* just to be sure. Just try it out - you will recognise a difference!
*
* [ 1998-06-14 ]
*
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
* and menus change their size on the fly.
*
* *) If for some reason the last scrolling position is not saved by
* lxdialog, it sets the scrolling so that the selected item is in the
* middle of the menu box, not at the bottom.
*
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
* This fixes a bug in Menuconfig where using ' ' to descend into menus
* would leave mis-synchronized lxdialog.scrltmp files lying around,
* fscanf would read in 'scroll', and eventually that value would get used.
*/
#include "dialog.h"
static int menu_width, item_x;
/*
* Print menu item
*/
static void
print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
{
int j;
char menu_item[menu_width+1];
strncpy(menu_item, item, menu_width);
menu_item[menu_width] = 0;
j = first_alpha(menu_item, "YyNnMmHh");
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
#if OLD_NCURSES
{
int i;
for (i = 0; i < menu_width; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
wattrset (win, selected ? item_selected_attr : item_attr);
mvwaddstr (win, choice, item_x, menu_item);
if (hotkey) {
wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
mvwaddch(win, choice, item_x+j, menu_item[j]);
}
if (selected) {
wmove (win, choice, item_x+1);
wrefresh (win);
}
}
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int item_no, int scroll,
int y, int x, int height)
{
int cur_y, cur_x;
getyx(win, cur_y, cur_x);
wmove(win, y, x);
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
y = y + height + 1;
wmove(win, y, x);
if ((height < item_no) && (scroll + height < item_no)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
wmove(win, cur_y, cur_x);
}
/*
* Display the termination buttons.
*/
static void
print_buttons (WINDOW *win, int height, int width, int selected)
{
int x = width / 2 - 16;
int y = height - 2;
print_button (win, "Select", y, x, selected == 0);
print_button (win, " Exit ", y, x + 12, selected == 1);
print_button (win, " Help ", y, x + 24, selected == 2);
wmove(win, y, x+1+12*selected);
wrefresh (win);
}
/*
* Display a menu for choosing among a number of options
*/
int
dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *current, int item_no,
struct dialog_list_item ** items)
{
int i, j, x, y, box_x, box_y;
int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
WINDOW *dialog, *menu;
FILE *f;
max_choice = MIN (menu_height, item_no);
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
menu_width = width - 6;
box_y = height - menu_height - 5;
box_x = (width - menu_width) / 2 - 1;
/* create new window for the menu */
menu = subwin (dialog, menu_height, menu_width,
y + box_y + 1, x + box_x + 1);
keypad (menu, TRUE);
/* draw a box around the menu items */
draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr);
/*
* Find length of longest item in order to center menu.
* Set 'choice' to default item.
*/
item_x = 0;
for (i = 0; i < item_no; i++) {
item_x = MAX (item_x, MIN(menu_width, strlen (items[i]->name) + 2));
if (strcmp(current, items[i]->tag) == 0) choice = i;
}
item_x = (menu_width - item_x) / 2;
/* get the scroll info from the temp file */
if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
(scroll+max_choice > choice) && (scroll >= 0) &&
(scroll+max_choice <= item_no) ) {
first_item = scroll;
choice = choice - scroll;
fclose(f);
} else {
scroll=0;
remove("lxdialog.scrltmp");
fclose(f);
f=NULL;
}
}
if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
if (choice >= item_no-max_choice/2)
scroll = first_item = item_no-max_choice;
else
scroll = first_item = choice - max_choice/2;
choice = choice - scroll;
}
/* Print the menu */
for (i=0; i < max_choice; i++) {
print_item (menu, items[first_item + i]->name, i, i == choice,
(items[first_item + i]->tag[0] != ':'));
}
wnoutrefresh (menu);
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
print_buttons (dialog, height, width, 0);
wmove (menu, choice, item_x+1);
wrefresh (menu);
while (key != ESC) {
key = wgetch(menu);
if (key < 256 && isalpha(key)) key = tolower(key);
if (strchr("ynmh", key))
i = max_choice;
else {
for (i = choice+1; i < max_choice; i++) {
j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
if (key == tolower(items[scroll + i]->name[j]))
break;
}
if (i == max_choice)
for (i = 0; i < max_choice; i++) {
j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
if (key == tolower(items[scroll + i]->name[j]))
break;
}
}
if (i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE) {
print_item (menu, items[scroll + choice]->name, choice, FALSE,
(items[scroll + choice]->tag[0] != ':'));
if (key == KEY_UP || key == '-') {
if (choice < 2 && scroll) {
/* Scroll menu down */
scrollok (menu, TRUE);
wscrl (menu, -1);
scrollok (menu, FALSE);
scroll--;
print_item (menu, items[scroll]->name, 0, FALSE,
(items[scroll]->tag[0] != ':'));
} else
choice = MAX(choice - 1, 0);
} else if (key == KEY_DOWN || key == '+') {
print_item (menu, items[scroll + choice]->name, choice, FALSE,
(items[scroll + choice]->tag[0] != ':'));
if ((choice > max_choice-3) &&
(scroll + max_choice < item_no)
) {
/* Scroll menu up */
scrollok (menu, TRUE);
scroll (menu);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[scroll + max_choice - 1]->name,
max_choice-1, FALSE,
(items[scroll + max_choice - 1]->tag[0] != ':'));
} else
choice = MIN(choice+1, max_choice-1);
} else if (key == KEY_PPAGE) {
scrollok (menu, TRUE);
for (i=0; (i < max_choice); i++) {
if (scroll > 0) {
wscrl (menu, -1);
scroll--;
print_item (menu, items[scroll]->name, 0, FALSE,
(items[scroll]->tag[0] != ':'));
} else {
if (choice > 0)
choice--;
}
}
scrollok (menu, FALSE);
} else if (key == KEY_NPAGE) {
for (i=0; (i < max_choice); i++) {
if (scroll+max_choice < item_no) {
scrollok (menu, TRUE);
scroll(menu);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[scroll + max_choice - 1]->name,
max_choice-1, FALSE,
(items[scroll + max_choice - 1]->tag[0] != ':'));
} else {
if (choice+1 < max_choice)
choice++;
}
}
} else
choice = i;
print_item (menu, items[scroll + choice]->name, choice, TRUE,
(items[scroll + choice]->tag[0] != ':'));
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
wnoutrefresh (dialog);
wrefresh (menu);
continue; /* wait for another key press */
}
switch (key) {
case KEY_LEFT:
case TAB:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (menu);
break;
case ' ':
case 's':
case 'y':
case 'n':
case 'm':
case '/':
/* save scroll info */
if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
fprintf(f,"%d\n",scroll);
fclose(f);
}
delwin (dialog);
items[scroll + choice]->selected = 1;
switch (key) {
case 's': return 3;
case 'y': return 3;
case 'n': return 4;
case 'm': return 5;
case ' ': return 6;
case '/': return 7;
}
return 0;
case 'h':
case '?':
button = 2;
case '\n':
delwin (dialog);
items[scroll + choice]->selected = 1;
remove("lxdialog.scrltmp");
return button;
case 'e':
case 'x':
key = ESC;
case ESC:
break;
}
}
delwin (dialog);
remove("lxdialog.scrltmp");
return -1; /* ESC pressed */
}

View File

@ -0,0 +1,85 @@
/*
* msgbox.c -- implements the message box and info box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
*/
int
dialog_msgbox (const char *title, const char *prompt, int height, int width,
int pause)
{
int i, x, y, key = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 2);
if (pause) {
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
print_button (dialog, " Ok ",
height - 2, width / 2 - 4, TRUE);
wrefresh (dialog);
while (key != ESC && key != '\n' && key != ' ' &&
key != 'O' && key != 'o' && key != 'X' && key != 'x')
key = wgetch (dialog);
} else {
key = '\n';
wrefresh (dialog);
}
delwin (dialog);
return key == ESC ? -1 : 0;
}

View File

@ -0,0 +1,556 @@
/*
* textbox.c -- implements the text box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
static void back_lines (int n);
static void print_page (WINDOW * win, int height, int width);
static void print_line (WINDOW * win, int row, int width);
static char *get_line (void);
static void print_position (WINDOW * win, int height, int width);
static int hscroll, fd, file_size, bytes_read;
static int begin_reached = 1, end_reached, page_length;
static char *buf, *page;
/*
* Display text from a file in a dialog box.
*/
int
dialog_textbox (const char *title, const char *file, int height, int width)
{
int i, x, y, cur_x, cur_y, fpos, key = 0;
int passed_end;
char search_term[MAX_LEN + 1];
WINDOW *dialog, *text;
search_term[0] = '\0'; /* no search term entered yet */
/* Open input file for reading */
if ((fd = open (file, O_RDONLY)) == -1) {
endwin ();
fprintf (stderr,
"\nCan't open input file in dialog_textbox().\n");
exit (-1);
}
/* Get file size. Actually, 'file_size' is the real file size - 1,
since it's only the last byte offset from the beginning */
if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
endwin ();
fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
exit (-1);
}
/* Restore file pointer to beginning of file after getting file size */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
/* Allocate space for read buffer */
if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
endwin ();
fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0'; /* mark end of valid data */
page = buf; /* page is pointer to start of page to be displayed */
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
/* Create window for text region, used for scrolling text */
text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
wattrset (text, dialog_attr);
wbkgdset (text, dialog_attr & A_COLOR);
keypad (text, TRUE);
/* register the new window, along with its borders */
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wnoutrefresh (dialog);
getyx (dialog, cur_y, cur_x); /* Save cursor position */
/* Print first page of text */
attr_clear (text, height - 4, width - 2, dialog_attr);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
while ((key != ESC) && (key != '\n')) {
key = wgetch (dialog);
switch (key) {
case 'E': /* Exit */
case 'e':
case 'X':
case 'x':
delwin (dialog);
free (buf);
close (fd);
return 0;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
/* First page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Yes, we have to read it in */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'G': /* Last page */
case KEY_END:
end_reached = 1;
/* Last page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos < file_size) { /* Yes, we have to read it in */
if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf + bytes_read;
back_lines (height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
if (!begin_reached) {
back_lines (page_length + 1);
/* We don't call print_page() here but use scrolling to ensure
faster screen update. However, 'end_reached' and
'page_length' should still be updated, and 'page' should
point to start of next page. This is done by calling
get_line() in the following 'for' loop. */
scrollok (text, TRUE);
wscrl (text, -1); /* Scroll text region down one line */
scrollok (text, FALSE);
page_length = 0;
passed_end = 0;
for (i = 0; i < height - 4; i++) {
if (!i) {
/* print first line of page */
print_line (text, 0, width - 2);
wnoutrefresh (text);
} else
/* Called to update 'end_reached' and 'page' */
get_line ();
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'B': /* Previous page */
case 'b':
case KEY_PPAGE:
if (begin_reached)
break;
back_lines (page_length + height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
if (!end_reached) {
begin_reached = 0;
scrollok (text, TRUE);
scroll (text); /* Scroll text region up one line */
scrollok (text, FALSE);
print_line (text, height - 5, width - 2);
wnoutrefresh (text);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case KEY_NPAGE: /* Next page */
case ' ':
if (end_reached)
break;
begin_reached = 0;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
case 'h':
case KEY_LEFT:
if (hscroll <= 0)
break;
if (key == '0')
hscroll = 0;
else
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'L': /* Scroll right */
case 'l':
case KEY_RIGHT:
if (hscroll >= MAX_LEN)
break;
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case ESC:
break;
}
}
delwin (dialog);
free (buf);
close (fd);
return 1; /* ESC pressed */
}
/*
* Go back 'n' lines in text file. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'.
*/
static void
back_lines (int n)
{
int i, fpos;
begin_reached = 0;
/* We have to distinguish between end_reached and !end_reached
since at end of file, the line is not ended by a '\n'.
The code inside 'if' basically does a '--page' to move one
character backward so as to skip '\n' of the previous line */
if (!end_reached) {
/* Either beginning of buffer or beginning of file reached? */
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Not beginning of file yet */
/* We've reached beginning of buffer, but not beginning of
file yet, so read previous part of file into buffer.
Note that we only move backward for BUF_SIZE/2 bytes,
but not BUF_SIZE bytes to avoid re-reading again in
print_page() later */
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
== -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
if (*(--page) != '\n') { /* '--page' here */
/* Something's wrong... */
endwin ();
fprintf (stderr, "\nInternal error in back_lines().\n");
exit (-1);
}
}
/* Go back 'n' lines */
for (i = 0; i < n; i++)
do {
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) {
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
SEEK_CUR) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer"
" in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in "
"back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
} while (*(--page) != '\n');
page++;
}
/*
* Print a new page of text. Called by dialog_textbox().
*/
static void
print_page (WINDOW * win, int height, int width)
{
int i, passed_end = 0;
page_length = 0;
for (i = 0; i < height; i++) {
print_line (win, i, width);
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
wnoutrefresh (win);
}
/*
* Print a new line of text. Called by dialog_textbox() and print_page().
*/
static void
print_line (WINDOW * win, int row, int width)
{
int y, x;
char *line;
line = get_line ();
line += MIN (strlen (line), hscroll); /* Scroll horizontally */
wmove (win, row, 0); /* move cursor to correct line */
waddch (win, ' ');
waddnstr (win, line, MIN (strlen (line), width - 2));
getyx (win, y, x);
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int i;
for (i = 0; i < width - x; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
}
/*
* Return current line of text. Called by dialog_textbox() and print_line().
* 'page' should point to start of current line before calling, and will be
* updated to point to start of next line.
*/
static char *
get_line (void)
{
int i = 0, fpos;
static char line[MAX_LEN + 1];
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
/* Either end of file or end of buffer reached */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"get_line().\n");
exit (-1);
}
if (fpos < file_size) { /* Not end of file yet */
/* We've reached end of buffer, but not end of file yet,
so read next part of file into buffer */
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in get_line().\n");
exit (-1);
}
buf[bytes_read] = '\0';
page = buf;
} else {
if (!end_reached)
end_reached = 1;
break;
}
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
/* Truncate lines longer than MAX_LEN characters */
if (i == MAX_LEN)
line[i++] = '\0';
page++;
}
}
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
page++; /* move pass '\n' */
return line;
}
/*
* Print current position
*/
static void
print_position (WINDOW * win, int height, int width)
{
int fpos, percent;
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in print_position().\n");
exit (-1);
}
wattrset (win, position_indicator_attr);
wbkgdset (win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove (win, height - 3, width - 9);
wprintw (win, "(%3d%%)", percent);
}

View File

@ -0,0 +1,375 @@
/*
* util.c
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/* use colors by default? */
bool use_colors = 1;
const char *backtitle = NULL;
const char *dialog_result;
/*
* Attribute values, default is for mono display
*/
chtype attributes[] =
{
A_NORMAL, /* screen_attr */
A_NORMAL, /* shadow_attr */
A_NORMAL, /* dialog_attr */
A_BOLD, /* title_attr */
A_NORMAL, /* border_attr */
A_REVERSE, /* button_active_attr */
A_DIM, /* button_inactive_attr */
A_REVERSE, /* button_key_active_attr */
A_BOLD, /* button_key_inactive_attr */
A_REVERSE, /* button_label_active_attr */
A_NORMAL, /* button_label_inactive_attr */
A_NORMAL, /* inputbox_attr */
A_NORMAL, /* inputbox_border_attr */
A_NORMAL, /* searchbox_attr */
A_BOLD, /* searchbox_title_attr */
A_NORMAL, /* searchbox_border_attr */
A_BOLD, /* position_indicator_attr */
A_NORMAL, /* menubox_attr */
A_NORMAL, /* menubox_border_attr */
A_NORMAL, /* item_attr */
A_REVERSE, /* item_selected_attr */
A_BOLD, /* tag_attr */
A_REVERSE, /* tag_selected_attr */
A_BOLD, /* tag_key_attr */
A_REVERSE, /* tag_key_selected_attr */
A_BOLD, /* check_attr */
A_REVERSE, /* check_selected_attr */
A_BOLD, /* uarrow_attr */
A_BOLD /* darrow_attr */
};
#include "colors.h"
/*
* Table of color values
*/
int color_table[][3] =
{
{SCREEN_FG, SCREEN_BG, SCREEN_HL},
{SHADOW_FG, SHADOW_BG, SHADOW_HL},
{DIALOG_FG, DIALOG_BG, DIALOG_HL},
{TITLE_FG, TITLE_BG, TITLE_HL},
{BORDER_FG, BORDER_BG, BORDER_HL},
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
BUTTON_LABEL_INACTIVE_HL},
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
{ITEM_FG, ITEM_BG, ITEM_HL},
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
{TAG_FG, TAG_BG, TAG_HL},
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
{CHECK_FG, CHECK_BG, CHECK_HL},
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
{UARROW_FG, UARROW_BG, UARROW_HL},
{DARROW_FG, DARROW_BG, DARROW_HL},
}; /* color_table */
/*
* Set window to attribute 'attr'
*/
void
attr_clear (WINDOW * win, int height, int width, chtype attr)
{
int i, j;
wattrset (win, attr);
for (i = 0; i < height; i++) {
wmove (win, i, 0);
for (j = 0; j < width; j++)
waddch (win, ' ');
}
touchwin (win);
}
void dialog_clear (void)
{
attr_clear (stdscr, LINES, COLS, screen_attr);
/* Display background title if it exists ... - SLH */
if (backtitle != NULL) {
int i;
wattrset (stdscr, screen_attr);
mvwaddstr (stdscr, 0, 1, (char *)backtitle);
wmove (stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++)
waddch (stdscr, ACS_HLINE);
}
wnoutrefresh (stdscr);
}
/*
* Do some initialization for dialog
*/
void
init_dialog (void)
{
initscr (); /* Init curses */
keypad (stdscr, TRUE);
cbreak ();
noecho ();
if (use_colors) /* Set up colors */
color_setup ();
dialog_clear ();
}
/*
* Setup for color display
*/
void
color_setup (void)
{
int i;
if (has_colors ()) { /* Terminal supports color? */
start_color ();
/* Initialize color pairs */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
init_pair (i + 1, color_table[i][0], color_table[i][1]);
/* Setup color attributes */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
attributes[i] = C_ATTR (color_table[i][2], i + 1);
}
}
/*
* End using dialog functions.
*/
void
end_dialog (void)
{
endwin ();
}
/*
* Print a string of text in a window, automatically wrap around to the
* next line if the string is too long to fit on one line. Newline
* characters '\n' are replaced by spaces. We start on a new line
* if there is no room for at least 4 nonblanks following a double-space.
*/
void
print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
{
int newl, cur_x, cur_y;
int i, prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
strcpy (tempstr, prompt);
prompt_len = strlen(tempstr);
/*
* Remove newlines
*/
for(i=0; i<prompt_len; i++) {
if(tempstr[i] == '\n') tempstr[i] = ' ';
}
if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove (win, y, (width - prompt_len) / 2);
waddstr (win, tempstr);
} else {
cur_x = x;
cur_y = y;
newl = 1;
word = tempstr;
while (word && *word) {
sp = index(word, ' ');
if (sp)
*sp++ = 0;
/* Wrap to next line if either the word does not fit,
or it is the first word of a new sentence, and it is
short, and the next word does not fit. */
room = width - cur_x;
wlen = strlen(word);
if (wlen > room ||
(newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
&& (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
cur_y++;
cur_x = x;
}
wmove (win, cur_y, cur_x);
waddstr (win, word);
getyx (win, cur_y, cur_x);
cur_x++;
if (sp && *sp == ' ') {
cur_x++; /* double space */
while (*++sp == ' ');
newl = 1;
} else
newl = 0;
word = sp;
}
}
}
/*
* Print a button
*/
void
print_button (WINDOW * win, const char *label, int y, int x, int selected)
{
int i, temp;
wmove (win, y, x);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, "<");
temp = strspn (label, " ");
label += temp;
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
for (i = 0; i < temp; i++)
waddch (win, ' ');
wattrset (win, selected ? button_key_active_attr
: button_key_inactive_attr);
waddch (win, label[0]);
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
waddstr (win, (char *)label + 1);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, ">");
wmove (win, y, x + temp + 1);
}
/*
* Draw a rectangular box with line drawing characters
*/
void
draw_box (WINDOW * win, int y, int x, int height, int width,
chtype box, chtype border)
{
int i, j;
wattrset (win, 0);
for (i = 0; i < height; i++) {
wmove (win, y + i, x);
for (j = 0; j < width; j++)
if (!i && !j)
waddch (win, border | ACS_ULCORNER);
else if (i == height - 1 && !j)
waddch (win, border | ACS_LLCORNER);
else if (!i && j == width - 1)
waddch (win, box | ACS_URCORNER);
else if (i == height - 1 && j == width - 1)
waddch (win, box | ACS_LRCORNER);
else if (!i)
waddch (win, border | ACS_HLINE);
else if (i == height - 1)
waddch (win, box | ACS_HLINE);
else if (!j)
waddch (win, border | ACS_VLINE);
else if (j == width - 1)
waddch (win, box | ACS_VLINE);
else
waddch (win, box | ' ');
}
}
/*
* Draw shadows along the right and bottom edge to give a more 3D look
* to the boxes
*/
void
draw_shadow (WINDOW * win, int y, int x, int height, int width)
{
int i;
if (has_colors ()) { /* Whether terminal supports color? */
wattrset (win, shadow_attr);
wmove (win, y + height, x + 2);
for (i = 0; i < width; i++)
waddch (win, winch (win) & A_CHARTEXT);
for (i = y + 1; i < y + height + 1; i++) {
wmove (win, i, x + width);
waddch (win, winch (win) & A_CHARTEXT);
waddch (win, winch (win) & A_CHARTEXT);
}
wnoutrefresh (win);
}
}
/*
* Return the position of the first alphabetic character in a string.
*/
int
first_alpha(const char *string, const char *exempt)
{
int i, in_paren=0, c;
for (i = 0; i < strlen(string); i++) {
c = tolower(string[i]);
if (strchr("<[(", c)) ++in_paren;
if (strchr(">])", c) && in_paren > 0) --in_paren;
if ((! in_paren) && isalpha(c) &&
strchr(exempt, c) == 0)
return i;
}
return 0;
}
/*
* Get the first selected item in the dialog_list_item list.
*/
struct dialog_list_item *
first_sel_item(int item_no, struct dialog_list_item ** items)
{
int i;
for (i = 0; i < item_no; i++) {
if (items[i]->selected)
return items[i];
}
return NULL;
}

View File

@ -0,0 +1,118 @@
/*
* yesno.c -- implements the yes/no box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "dialog.h"
/*
* Display termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 10;
int y = height - 2;
print_button (dialog, " Yes ", y, x, selected == 0);
print_button (dialog, " No ", y, x + 13, selected == 1);
wmove(dialog, y, x+1 + 13*selected );
wrefresh (dialog);
}
/*
* Display a dialog box with two buttons - Yes and No
*/
int
dialog_yesno (const char *title, const char *prompt, int height, int width)
{
int i, x, y, key = 0, button = 0;
WINDOW *dialog;
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
draw_shadow (stdscr, y, x, height, width);
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
print_buttons(dialog, height, width, 0);
while (key != ESC) {
key = wgetch (dialog);
switch (key) {
case 'Y':
case 'y':
delwin (dialog);
return 0;
case 'N':
case 'n':
delwin (dialog);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case ' ':
case '\n':
delwin (dialog);
return button;
case ESC:
break;
}
}
delwin (dialog);
return -1; /* ESC pressed */
}

View File

@ -0,0 +1,977 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*
* Introduced single menu mode (show all sub-menus in one large tree).
* 2002-11-06 Petr Baudis <pasky@ucw.cz>
*
* Directly use liblxdialog library routines.
* 2002-11-14 Petr Baudis <pasky@ucw.cz>
*/
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/termios.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "lxdialog/dialog.h"
#define LKC_DIRECT_LINK
#include "lkc.h"
static char menu_backtitle[128];
static const char mconf_readme[] =
"Overview\n"
"--------\n"
"Some features may be built directly into axTLS. Some features\n"
"may be completely removed altogether. There are also certain\n"
"parameters which are not really features, but must be\n"
"entered in as decimal or hexadecimal numbers or possibly text.\n"
"\n"
"Menu items beginning with [*] or [ ] represent features\n"
"configured to be built in or removed respectively.\n"
"\n"
"To change any of these features, highlight it with the cursor\n"
"keys and press <Y> to build it in or <N> to removed it.\n"
"You may also press the <Space Bar> to cycle\n"
"through the available options (ie. Y->N->Y).\n"
"\n"
"Some additional keyboard hints:\n"
"\n"
"Menus\n"
"----------\n"
"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
" you wish to change or submenu wish to select and press <Enter>.\n"
" Submenus are designated by \"--->\".\n"
"\n"
" Shortcut: Press the option's highlighted letter (hotkey).\n"
" Pressing a hotkey more than once will sequence\n"
" through all visible items which use that hotkey.\n"
"\n"
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
" unseen options into view.\n"
"\n"
"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
" and press <ENTER>.\n"
"\n"
" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
" using those letters. You may press a single <ESC>, but\n"
" there is a delayed response which you may find annoying.\n"
"\n"
" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
" <Exit> and <Help>\n"
"\n"
"o To get help with an item, use the cursor keys to highlight <Help>\n"
" and Press <ENTER>.\n"
"\n"
" Shortcut: Press <H> or <?>.\n"
"\n"
"\n"
"Radiolists (Choice lists)\n"
"-----------\n"
"o Use the cursor keys to select the option you wish to set and press\n"
" <S> or the <SPACE BAR>.\n"
"\n"
" Shortcut: Press the first letter of the option you wish to set then\n"
" press <S> or <SPACE BAR>.\n"
"\n"
"o To see available help for the item, use the cursor keys to highlight\n"
" <Help> and Press <ENTER>.\n"
"\n"
" Shortcut: Press <H> or <?>.\n"
"\n"
" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
" <Help>\n"
"\n"
"\n"
"Data Entry\n"
"-----------\n"
"o Enter the requested information and press <ENTER>\n"
" If you are entering hexadecimal values, it is not necessary to\n"
" add the '0x' prefix to the entry.\n"
"\n"
"o For help, use the <TAB> or cursor keys to highlight the help option\n"
" and press <ENTER>. You can try <TAB><H> as well.\n"
"\n"
"\n"
"Text Box (Help Window)\n"
"--------\n"
"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
" who are familiar with less and lynx.\n"
"\n"
"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
"\n"
"\n"
"Alternate Configuration Files\n"
"-----------------------------\n"
"Menuconfig supports the use of alternate configuration files for\n"
"those who, for various reasons, find it necessary to switch\n"
"between different configurations.\n"
"\n"
"At the end of the main menu you will find two options. One is\n"
"for saving the current configuration to a file of your choosing.\n"
"The other option is for loading a previously saved alternate\n"
"configuration.\n"
"\n"
"Even if you don't use alternate configuration files, but you\n"
"find during a Menuconfig session that you have completely messed\n"
"up your settings, you may use the \"Load Alternate...\" option to\n"
"restore your previously saved settings from \".config\" without\n"
"restarting Menuconfig.\n"
"\n"
"Other information\n"
"-----------------\n"
"If you use Menuconfig in an XTERM window make sure you have your\n"
"$TERM variable set to point to a xterm definition which supports color.\n"
"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
"display correctly in a RXVT window because rxvt displays only one\n"
"intensity of color, bright.\n"
"\n"
"Menuconfig will display larger menus on screens or xterms which are\n"
"set to display more than the standard 25 row by 80 column geometry.\n"
"In order for this to work, the \"stty size\" command must be able to\n"
"display the screen's current row and column geometry. I STRONGLY\n"
"RECOMMEND that you make sure you do NOT have the shell variables\n"
"LINES and COLUMNS exported into your environment. Some distributions\n"
"export those variables via /etc/profile. Some ncurses programs can\n"
"become confused when those variables (LINES & COLUMNS) don't reflect\n"
"the true screen size.\n"
"\n"
"Optional personality available\n"
"------------------------------\n"
"If you prefer to have all of the options listed in a single\n"
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
"\n"
"make MENUCONFIG_MODE=single_menu menuconfig\n"
"\n"
"<Enter> will then unroll the appropriate category, or enfold it if it\n"
"is already unrolled.\n"
"\n"
"Note that this mode can eventually be a little more CPU expensive\n"
"(especially with a larger number of unrolled categories) than the\n"
"default mode.\n",
menu_instructions[] =
"Arrow keys navigate the menu. "
"<Enter> selects submenus --->. "
"Highlighted letters are hotkeys. "
"Pressing <Y> selectes a feature, while <N> will exclude a feature. "
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
"Legend: [*] feature is selected [ ] feature is excluded",
radiolist_instructions[] =
"Use the arrow keys to navigate this window or "
"press the hotkey of the item you wish to select "
"followed by the <SPACE BAR>. "
"Press <?> for additional information about this option.",
inputbox_instructions_int[] =
"Please enter a decimal value. "
"Fractions will not be accepted. "
"Use the <TAB> key to move from the input field to the buttons below it.",
inputbox_instructions_hex[] =
"Please enter a hexadecimal value. "
"Use the <TAB> key to move from the input field to the buttons below it.",
inputbox_instructions_string[] =
"Please enter a string value. "
"Use the <TAB> key to move from the input field to the buttons below it.",
setmod_text[] =
"This feature depends on another which has been configured as a module.\n"
"As a result, this feature will be built as a module.",
nohelp_text[] =
"There is no help available for this option.\n",
load_config_text[] =
"Enter the name of the configuration file you wish to load. "
"Accept the name shown to restore the configuration you "
"last retrieved. Leave blank to abort.",
load_config_help[] =
"\n"
"For various reasons, one may wish to keep several different axTLS\n"
"configurations available on a single machine.\n"
"\n"
"If you have saved a previous configuration in a file other than the\n"
"axTLS's default, entering the name of the file here will allow you\n"
"to modify that configuration.\n"
"\n"
"If you are uncertain, then you have probably never used alternate\n"
"configuration files. You should therefor leave this blank to abort.\n",
save_config_text[] =
"Enter a filename to which this configuration should be saved "
"as an alternate. Leave blank to abort.",
save_config_help[] =
"\n"
"For various reasons, one may wish to keep different axTLS\n"
"configurations available on a single machine.\n"
"\n"
"Entering a file name here will allow you to later retrieve, modify\n"
"and use the current configuration as an alternate to whatever\n"
"configuration options you have selected at that time.\n"
"\n"
"If you are uncertain what all this means then you should probably\n"
"leave this blank.\n",
search_help[] =
"\n"
"Search for CONFIG_ symbols and display their relations.\n"
"Example: search for \"^FOO\"\n"
"Result:\n"
"-----------------------------------------------------------------\n"
"Symbol: FOO [=m]\n"
"Prompt: Foo bus is used to drive the bar HW\n"
"Defined at drivers/pci/Kconfig:47\n"
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
"Location:\n"
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
" -> PCI support (PCI [=y])\n"
" -> PCI access mode (<choice> [=y])\n"
"Selects: LIBCRC32\n"
"Selected by: BAR\n"
"-----------------------------------------------------------------\n"
"o The line 'Prompt:' shows the text used in the menu structure for\n"
" this CONFIG_ symbol\n"
"o The 'Defined at' line tell at what file / line number the symbol\n"
" is defined\n"
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
" this symbol to be visible in the menu (selectable)\n"
"o The 'Location:' lines tell where in the menu structure this symbol\n"
" is located\n"
" A location followed by a [=y] indicate that this is a selectable\n"
" menu item - and current value is displayed inside brackets.\n"
"o The 'Selects:' line tell what symbol will be automatically\n"
" selected if this symbol is selected (y or m)\n"
"o The 'Selected by' line tell what symbol has selected this symbol\n"
"\n"
"Only relevant lines are shown.\n"
"\n\n"
"Search examples:\n"
"Examples: USB => find all CONFIG_ symbols containing USB\n"
" ^USB => find all CONFIG_ symbols starting with USB\n"
" USB$ => find all CONFIG_ symbols ending with USB\n"
"\n";
static char filename[PATH_MAX+1] = ".config";
static int indent;
static struct termios ios_org;
static int rows = 0, cols = 0;
static struct menu *current_menu;
static int child_count;
static int single_menu_mode;
static struct dialog_list_item *items[16384]; /* FIXME: This ought to be dynamic. */
static int item_no;
static void conf(struct menu *menu);
static void conf_choice(struct menu *menu);
static void conf_string(struct menu *menu);
static void conf_load(void);
static void conf_save(void);
static void show_textbox(const char *title, const char *text, int r, int c);
static void show_helptext(const char *title, const char *text);
static void show_help(struct menu *menu);
static void show_file(const char *filename, const char *title, int r, int c);
static void init_wsize(void)
{
struct winsize ws;
char *env;
if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
rows = ws.ws_row;
cols = ws.ws_col;
}
if (!rows) {
env = getenv("LINES");
if (env)
rows = atoi(env);
if (!rows)
rows = 24;
}
if (!cols) {
env = getenv("COLUMNS");
if (env)
cols = atoi(env);
if (!cols)
cols = 80;
}
if (rows < 19 || cols < 80) {
fprintf(stderr, "Your display is too small to run Menuconfig!\n");
fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
exit(1);
}
rows -= 4;
cols -= 5;
}
static void cinit(void)
{
item_no = 0;
}
static void cmake(void)
{
items[item_no] = malloc(sizeof(struct dialog_list_item));
memset(items[item_no], 0, sizeof(struct dialog_list_item));
items[item_no]->tag = malloc(32); items[item_no]->tag[0] = 0;
items[item_no]->name = malloc(512); items[item_no]->name[0] = 0;
items[item_no]->namelen = 0;
item_no++;
}
static int cprint_name(const char *fmt, ...)
{
va_list ap;
int res;
if (!item_no)
cmake();
va_start(ap, fmt);
res = vsnprintf(items[item_no - 1]->name + items[item_no - 1]->namelen,
512 - items[item_no - 1]->namelen, fmt, ap);
if (res > 0)
items[item_no - 1]->namelen += res;
va_end(ap);
return res;
}
static int cprint_tag(const char *fmt, ...)
{
va_list ap;
int res;
if (!item_no)
cmake();
va_start(ap, fmt);
res = vsnprintf(items[item_no - 1]->tag, 32, fmt, ap);
va_end(ap);
return res;
}
static void cdone(void)
{
int i;
for (i = 0; i < item_no; i++) {
free(items[i]->tag);
free(items[i]->name);
free(items[i]);
}
item_no = 0;
}
static void get_prompt_str(struct gstr *r, struct property *prop)
{
int i, j;
struct menu *submenu[8], *menu;
str_printf(r, "Prompt: %s\n", prop->text);
str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
prop->menu->lineno);
if (!expr_is_yes(prop->visible.expr)) {
str_append(r, " Depends on: ");
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
submenu[i++] = menu;
if (i > 0) {
str_printf(r, " Location:\n");
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : "<choice>",
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
}
}
}
static void get_symbol_str(struct gstr *r, struct symbol *sym)
{
bool hit;
struct property *prop;
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
sym_get_string_value(sym));
for_all_prompts(sym, prop)
get_prompt_str(r, prop);
hit = false;
for_all_properties(sym, prop, P_SELECT) {
if (!hit) {
str_append(r, " Selects: ");
hit = true;
} else
str_printf(r, " && ");
expr_gstr_print(prop->expr, r);
}
if (hit)
str_append(r, "\n");
if (sym->rev_dep.expr) {
str_append(r, " Selected by: ");
expr_gstr_print(sym->rev_dep.expr, r);
str_append(r, "\n");
}
str_append(r, "\n\n");
}
static struct gstr get_relations_str(struct symbol **sym_arr)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym);
if (!i)
str_append(&res, "No matches found.\n");
return res;
}
static void search_conf(void)
{
struct symbol **sym_arr;
struct gstr res;
again:
switch (dialog_inputbox("Search Configuration Parameter",
"Enter Keyword", 10, 75,
NULL)) {
case 0:
break;
case 1:
show_helptext("Search Configuration", search_help);
goto again;
default:
return;
}
sym_arr = sym_re_search(dialog_input_result);
res = get_relations_str(sym_arr);
free(sym_arr);
show_textbox("Search Results", str_get(&res), 0, 0);
str_free(&res);
}
static void build_conf(struct menu *menu)
{
struct symbol *sym;
struct property *prop;
struct menu *child;
int type, tmp, doint = 2;
tristate val;
char ch;
if (!menu_is_visible(menu))
return;
sym = menu->sym;
prop = menu->prompt;
if (!sym) {
if (prop && menu != current_menu) {
const char *prompt = menu_get_prompt(menu);
switch (prop->type) {
case P_MENU:
child_count++;
cmake();
cprint_tag("m%p", menu);
if (single_menu_mode) {
cprint_name("%s%*c%s",
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
} else {
cprint_name(" %*c%s --->", indent + 1, ' ', prompt);
}
if (single_menu_mode && menu->data)
goto conf_childs;
return;
default:
if (prompt) {
child_count++;
cmake();
cprint_tag(":%p", menu);
cprint_name("---%*c%s", indent + 1, ' ', prompt);
}
}
} else
doint = 0;
goto conf_childs;
}
cmake();
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
struct symbol *def_sym = sym_get_choice_value(sym);
struct menu *def_menu = NULL;
child_count++;
for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child) && child->sym == def_sym)
def_menu = child;
}
val = sym_get_tristate_value(sym);
if (sym_is_changable(sym)) {
cprint_tag("t%p", menu);
switch (type) {
case S_BOOLEAN:
cprint_name("[%c]", val == no ? ' ' : '*');
break;
case S_TRISTATE:
switch (val) {
case yes: ch = '*'; break;
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
cprint_name("<%c>", ch);
break;
}
} else {
cprint_tag("%c%p", def_menu ? 't' : ':', menu);
cprint_name(" ");
}
cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
if (val == yes) {
if (def_menu) {
cprint_name(" (%s)", menu_get_prompt(def_menu));
cprint_name(" --->");
if (def_menu->list) {
indent += 2;
build_conf(def_menu);
indent -= 2;
}
}
return;
}
} else {
if (menu == current_menu) {
cprint_tag(":%p", menu);
cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
goto conf_childs;
}
child_count++;
val = sym_get_tristate_value(sym);
if (sym_is_choice_value(sym) && val == yes) {
cprint_tag(":%p", menu);
cprint_name(" ");
} else {
switch (type) {
case S_BOOLEAN:
cprint_tag("t%p", menu);
if (sym_is_changable(sym))
cprint_name("[%c]", val == no ? ' ' : '*');
else
cprint_name("---");
break;
case S_TRISTATE:
cprint_tag("t%p", menu);
switch (val) {
case yes: ch = '*'; break;
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
if (sym_is_changable(sym))
cprint_name("<%c>", ch);
else
cprint_name("---");
break;
default:
cprint_tag("s%p", menu);
tmp = cprint_name("(%s)", sym_get_string_value(sym));
tmp = indent - tmp + 4;
if (tmp < 0)
tmp = 0;
cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
goto conf_childs;
}
}
cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
if (menu->prompt->type == P_MENU) {
cprint_name(" --->");
return;
}
}
conf_childs:
indent += doint;
for (child = menu->list; child; child = child->next)
build_conf(child);
indent -= doint;
}
static void conf(struct menu *menu)
{
struct dialog_list_item *active_item = NULL;
struct menu *submenu;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
char active_entry[40];
int stat, type;
unlink("lxdialog.scrltmp");
active_entry[0] = 0;
while (1) {
indent = 0;
child_count = 0;
current_menu = menu;
cdone(); cinit();
build_conf(menu);
if (!child_count)
break;
if (menu == &rootmenu) {
cmake(); cprint_tag(":"); cprint_name("--- ");
cmake(); cprint_tag("L"); cprint_name("Load an Alternate Configuration File");
cmake(); cprint_tag("S"); cprint_name("Save Configuration to an Alternate File");
}
dialog_clear();
stat = dialog_menu(prompt ? prompt : "Main Menu",
menu_instructions, rows, cols, rows - 10,
active_entry, item_no, items);
if (stat < 0)
return;
if (stat == 1 || stat == 255)
break;
active_item = first_sel_item(item_no, items);
if (!active_item)
continue;
active_item->selected = 0;
strncpy(active_entry, active_item->tag, sizeof(active_entry));
active_entry[sizeof(active_entry)-1] = 0;
type = active_entry[0];
if (!type)
continue;
sym = NULL;
submenu = NULL;
if (sscanf(active_entry + 1, "%p", &submenu) == 1)
sym = submenu->sym;
switch (stat) {
case 0:
switch (type) {
case 'm':
if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data;
else
conf(submenu);
break;
case 't':
if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
conf(submenu);
break;
case 's':
conf_string(submenu);
break;
case 'L':
conf_load();
break;
case 'S':
conf_save();
break;
}
break;
case 2:
if (sym)
show_help(submenu);
else
show_helptext("README", mconf_readme);
break;
case 3:
if (type == 't') {
if (sym_set_tristate_value(sym, yes))
break;
if (sym_set_tristate_value(sym, mod))
show_textbox(NULL, setmod_text, 6, 74);
}
break;
case 4:
if (type == 't')
sym_set_tristate_value(sym, no);
break;
case 5:
if (type == 't')
sym_set_tristate_value(sym, mod);
break;
case 6:
if (type == 't')
sym_toggle_tristate_value(sym);
else if (type == 'm')
conf(submenu);
break;
case 7:
search_conf();
break;
}
}
}
static void show_textbox(const char *title, const char *text, int r, int c)
{
int fd;
fd = creat(".help.tmp", 0777);
write(fd, text, strlen(text));
close(fd);
show_file(".help.tmp", title, r, c);
unlink(".help.tmp");
}
static void show_helptext(const char *title, const char *text)
{
show_textbox(title, text, 0, 0);
}
static void show_help(struct menu *menu)
{
struct gstr help = str_new();
struct symbol *sym = menu->sym;
if (sym->help)
{
if (sym->name) {
str_printf(&help, "%s:\n\n", sym->name);
str_append(&help, sym->help);
str_append(&help, "\n");
}
} else {
str_append(&help, nohelp_text);
}
get_symbol_str(&help, sym);
show_helptext(menu_get_prompt(menu), str_get(&help));
str_free(&help);
}
static void show_file(const char *filename, const char *title, int r, int c)
{
while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0)
;
}
static void conf_choice(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
struct menu *child;
struct symbol *active;
active = sym_get_choice_value(menu->sym);
while (1) {
current_menu = menu;
cdone(); cinit();
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
cmake();
cprint_tag("%p", child);
cprint_name("%s", menu_get_prompt(child));
if (child->sym == sym_get_choice_value(menu->sym))
items[item_no - 1]->selected = 1; /* ON */
else if (child->sym == active)
items[item_no - 1]->selected = 2; /* SELECTED */
else
items[item_no - 1]->selected = 0; /* OFF */
}
switch (dialog_checklist(prompt ? prompt : "Main Menu",
radiolist_instructions, 15, 70, 6,
item_no, items, FLAG_RADIO)) {
case 0:
if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1)
break;
sym_set_tristate_value(child->sym, yes);
return;
case 1:
if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
show_help(child);
active = child->sym;
} else
show_help(menu);
break;
case 255:
return;
}
}
}
static void conf_string(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
while (1) {
char *heading;
switch (sym_get_type(menu->sym)) {
case S_INT:
heading = (char *) inputbox_instructions_int;
break;
case S_HEX:
heading = (char *) inputbox_instructions_hex;
break;
case S_STRING:
heading = (char *) inputbox_instructions_string;
break;
default:
heading = "Internal mconf error!";
/* panic? */;
}
switch (dialog_inputbox(prompt ? prompt : "Main Menu",
heading, 10, 75,
sym_get_string_value(menu->sym))) {
case 0:
if (sym_set_string_value(menu->sym, dialog_input_result))
return;
show_textbox(NULL, "You have made an invalid entry.", 5, 43);
break;
case 1:
show_help(menu);
break;
case 255:
return;
}
}
}
static void conf_load(void)
{
while (1) {
switch (dialog_inputbox(NULL, load_config_text, 11, 55,
filename)) {
case 0:
if (!dialog_input_result[0])
return;
if (!conf_read(dialog_input_result))
return;
show_textbox(NULL, "File does not exist!", 5, 38);
break;
case 1:
show_helptext("Load Alternate Configuration", load_config_help);
break;
case 255:
return;
}
}
}
static void conf_save(void)
{
while (1) {
switch (dialog_inputbox(NULL, save_config_text, 11, 55,
filename)) {
case 0:
if (!dialog_input_result[0])
return;
if (!conf_write(dialog_input_result))
return;
show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
break;
case 1:
show_helptext("Save Alternate Configuration", save_config_help);
break;
case 255:
return;
}
}
}
static void conf_cleanup(void)
{
tcsetattr(1, TCSAFLUSH, &ios_org);
unlink(".help.tmp");
}
static void winch_handler(int sig)
{
struct winsize ws;
if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
rows = 24;
cols = 80;
} else {
rows = ws.ws_row;
cols = ws.ws_col;
}
if (rows < 19 || cols < 80) {
end_dialog();
fprintf(stderr, "Your display is too small to run Menuconfig!\n");
fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
exit(1);
}
rows -= 4;
cols -= 5;
}
int main(int ac, char **av)
{
struct symbol *sym;
char *mode;
int stat;
conf_parse(av[1]);
conf_read(NULL);
sym = sym_lookup("VERSION", 0);
sym_calc_value(sym);
snprintf(menu_backtitle, 128, "axTLS v%s Configuration",
sym_get_string_value(sym));
mode = getenv("MENUCONFIG_MODE");
if (mode) {
if (!strcasecmp(mode, "single_menu"))
single_menu_mode = 1;
}
tcgetattr(1, &ios_org);
atexit(conf_cleanup);
init_wsize();
init_dialog();
signal(SIGWINCH, winch_handler);
conf(&rootmenu);
end_dialog();
/* Restart dialog to act more like when lxdialog was still separate */
init_dialog();
do {
stat = dialog_yesno(NULL,
"Do you wish to save your new axTLS configuration?", 5, 60);
} while (stat < 0);
end_dialog();
if (stat == 0) {
conf_write(NULL);
printf("\n\n"
"*** End of axTLS configuration.\n"
"*** Check the top-level Makefile for additional configuration options.\n\n");
} else
printf("\n\nYour axTLS configuration changes were NOT saved.\n\n");
return 0;
}

View File

@ -0,0 +1,390 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <stdlib.h>
#include <string.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
struct menu rootmenu;
static struct menu **last_entry_ptr;
struct file *file_list;
struct file *current_file;
static void menu_warn(struct menu *menu, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
static void prop_warn(struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void menu_init(void)
{
current_entry = current_menu = &rootmenu;
last_entry_ptr = &rootmenu.list;
}
void menu_add_entry(struct symbol *sym)
{
struct menu *menu;
menu = malloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
menu->sym = sym;
menu->parent = current_menu;
menu->file = current_file;
menu->lineno = zconf_lineno();
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
}
void menu_end_entry(void)
{
}
void menu_add_menu(void)
{
current_menu = current_entry;
last_entry_ptr = &current_entry->list;
}
void menu_end_menu(void)
{
last_entry_ptr = &current_menu->next;
current_menu = current_menu->parent;
}
struct expr *menu_check_dep(struct expr *e)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
e->left.expr = menu_check_dep(e->left.expr);
break;
case E_OR:
case E_AND:
e->left.expr = menu_check_dep(e->left.expr);
e->right.expr = menu_check_dep(e->right.expr);
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
if (e->left.sym == &symbol_mod)
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
break;
default:
break;
}
return e;
}
void menu_add_dep(struct expr *dep)
{
current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
}
void menu_set_type(int type)
{
struct symbol *sym = current_entry->sym;
if (sym->type == type)
return;
if (sym->type == S_UNKNOWN) {
sym->type = type;
return;
}
menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
sym->name ? sym->name : "<choice>",
sym_type_name(sym->type), sym_type_name(type));
}
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
{
struct property *prop = prop_alloc(type, current_entry->sym);
prop->menu = current_entry;
prop->text = prompt;
prop->expr = expr;
prop->visible.expr = menu_check_dep(dep);
if (prompt) {
if (current_entry->prompt)
menu_warn(current_entry, "prompt redefined\n");
current_entry->prompt = prop;
}
return prop;
}
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
{
menu_add_prop(type, prompt, NULL, dep);
}
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
menu_add_prop(type, NULL, expr, dep);
}
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
{
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
}
void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL)
prop_warn(prop,
"default for config symbol '%'"
" must be a single symbol", sym->name);
break;
case P_SELECT:
sym2 = prop_get_symbol(prop);
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
prop_warn(prop,
"config symbol '%s' uses select, but is "
"not boolean or tristate", sym->name);
else if (sym2->type == S_UNKNOWN)
prop_warn(prop,
"'select' used by config symbol '%s' "
"refer to undefined symbol '%s'",
sym->name, sym2->name);
else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
prop_warn(prop,
"'%s' has wrong type. 'select' only "
"accept arguments of boolean and "
"tristate type", sym2->name);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed "
"for int or hex symbols");
if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
!sym_string_valid(sym, prop->expr->right.sym->name))
prop_warn(prop, "range is invalid");
break;
default:
;
}
}
}
void menu_finalize(struct menu *parent)
{
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
struct expr *parentdep, *basedep, *dep, *dep2, **ep;
sym = parent->sym;
if (parent->list) {
if (sym && sym_is_choice(sym)) {
/* find the first choice value and find out choice type */
for (menu = parent->list; menu; menu = menu->next) {
if (menu->sym) {
current_entry = parent;
menu_set_type(menu->sym->type);
current_entry = menu;
menu_set_type(sym->type);
break;
}
}
parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt)
parentdep = parent->prompt->visible.expr;
else
parentdep = parent->dep;
for (menu = parent->list; menu; menu = menu->next) {
basedep = expr_transform(menu->dep);
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
if (menu->sym)
prop = menu->sym->prop;
else
prop = menu->prompt;
for (; prop; prop = prop->next) {
if (prop->menu != menu)
continue;
dep = expr_transform(prop->visible.expr);
dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE)
dep = expr_trans_bool(dep);
prop->visible.expr = dep;
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
}
}
for (menu = parent->list; menu; menu = menu->next)
menu_finalize(menu);
} else if (sym) {
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
basedep = expr_eliminate_dups(expr_transform(basedep));
last_menu = NULL;
for (menu = parent->next; menu; menu = menu->next) {
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
if (!expr_contains_symbol(dep, sym))
break;
if (expr_depends_symbol(dep, sym))
goto next;
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
dep = expr_eliminate_dups(expr_transform(dep));
dep2 = expr_copy(basedep);
expr_eliminate_eq(&dep, &dep2);
expr_free(dep);
if (!expr_is_yes(dep2)) {
expr_free(dep2);
break;
}
expr_free(dep2);
next:
menu_finalize(menu);
menu->parent = parent;
last_menu = menu;
}
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
last_menu->next = NULL;
}
}
for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) {
menu->sym->flags |= SYMBOL_CHOICEVAL;
if (!menu->prompt)
menu_warn(menu, "choice value must have a prompt");
for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->type == P_PROMPT && prop->menu != menu) {
prop_warn(prop, "choice values "
"currently only support a "
"single prompt");
}
if (prop->type == P_DEFAULT)
prop_warn(prop, "defaults for choice "
"values not supported");
}
current_entry = menu;
menu_set_type(sym->type);
menu_add_symbol(P_CHOICE, sym, NULL);
prop = sym_get_choice_prop(sym);
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
;
*ep = expr_alloc_one(E_CHOICE, NULL);
(*ep)->right.sym = menu->sym;
}
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
for (last_menu = menu->list; ; last_menu = last_menu->next) {
last_menu->parent = parent;
if (!last_menu->next)
break;
}
last_menu->next = menu->next;
menu->next = menu->list;
menu->list = NULL;
}
}
if (sym && !(sym->flags & SYMBOL_WARNED)) {
if (sym->type == S_UNKNOWN)
menu_warn(parent, "config symbol defined "
"without type\n");
if (sym_is_choice(sym) && !parent->prompt)
menu_warn(parent, "choice must have a prompt\n");
/* Check properties connected to this symbol */
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
}
if (sym && !sym_is_optional(sym) && parent->prompt) {
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
expr_alloc_and(parent->prompt->visible.expr,
expr_alloc_symbol(&symbol_mod)));
}
}
bool menu_is_visible(struct menu *menu)
{
struct menu *child;
struct symbol *sym;
tristate visible;
if (!menu->prompt)
return false;
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
visible = menu->prompt->visible.tri;
} else
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
if (visible != no)
return true;
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
for (child = menu->list; child; child = child->next)
if (menu_is_visible(child))
return true;
return false;
}
const char *menu_get_prompt(struct menu *menu)
{
if (menu->prompt)
return menu->prompt->text;
else if (menu->sym)
return menu->sym->name;
return NULL;
}
struct menu *menu_get_root_menu(struct menu *menu)
{
return &rootmenu;
}
struct menu *menu_get_parent_menu(struct menu *menu)
{
enum prop_type type;
for (; menu != &rootmenu; menu = menu->parent) {
type = menu->prompt ? menu->prompt->type : 0;
if (type == P_MENU)
break;
}
return menu;
}

67
config/scripts/config/mkconfigs Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh
#
# Copyright (C) 2002 Khalid Aziz <khalid_aziz at hp.com>
# Copyright (C) 2002 Randy Dunlap <rddunlap at osdl.org>
# Copyright (C) 2002 Al Stone <ahs3 at fc.hp.com>
# Copyright (C) 2002 Hewlett-Packard Company
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Busybox version by Matteo Croce <3297627799 at wind.it>
#
# Rules to generate bbconfig.h from .config:
# - Retain lines that begin with "CONFIG_"
# - Retain lines that begin with "# CONFIG_"
# - lines that use double-quotes must \\-escape-quote them
if [ $# -lt 1 ]
then
config=.config
else config=$1
fi
echo "#ifndef _BBCONFIG_H"
echo "#define _BBCONFIG_H"
echo \
"/*
* busybox configuration options.
*
* 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, GOOD TITLE or
* NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*
* This file is generated automatically by scripts/config/mkconfigs.
* Do not edit.
*
*/"
echo "static char const bbconfig_config[] ="
echo "\"CONFIG_BEGIN=n\\n\\"
echo "`sed 's/\"/\\\\\"/g' $config | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `"
echo "CONFIG_END=n\\n\";"
echo "#endif /* _BBCONFIG_H */"

View File

@ -0,0 +1,809 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include <sys/utsname.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
struct symbol symbol_yes = {
.name = "y",
.curr = { "y", yes },
.flags = SYMBOL_YES|SYMBOL_VALID,
}, symbol_mod = {
.name = "m",
.curr = { "m", mod },
.flags = SYMBOL_MOD|SYMBOL_VALID,
}, symbol_no = {
.name = "n",
.curr = { "n", no },
.flags = SYMBOL_NO|SYMBOL_VALID,
}, symbol_empty = {
.name = "",
.curr = { "", no },
.flags = SYMBOL_VALID,
};
int sym_change_count;
struct symbol *modules_sym;
tristate modules_val;
void sym_add_default(struct symbol *sym, const char *def)
{
struct property *prop = prop_alloc(P_DEFAULT, sym);
prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
}
void sym_init(void)
{
struct symbol *sym;
char *p;
static bool inited = false;
if (inited)
return;
inited = true;
sym = sym_lookup("VERSION", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
p = getenv("VERSION");
if (p)
sym_add_default(sym, p);
sym = sym_lookup("TARGET_ARCH", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
p = getenv("TARGET_ARCH");
if (p)
sym_add_default(sym, p);
}
enum symbol_type sym_get_type(struct symbol *sym)
{
enum symbol_type type = sym->type;
if (type == S_TRISTATE) {
if (sym_is_choice_value(sym) && sym->visible == yes)
type = S_BOOLEAN;
else if (modules_val == no)
type = S_BOOLEAN;
}
return type;
}
const char *sym_type_name(enum symbol_type type)
{
switch (type) {
case S_BOOLEAN:
return "boolean";
case S_TRISTATE:
return "tristate";
case S_INT:
return "integer";
case S_HEX:
return "hex";
case S_STRING:
return "string";
case S_UNKNOWN:
return "unknown";
case S_OTHER:
break;
}
return "???";
}
struct property *sym_get_choice_prop(struct symbol *sym)
{
struct property *prop;
for_all_choices(sym, prop)
return prop;
return NULL;
}
struct property *sym_get_default_prop(struct symbol *sym)
{
struct property *prop;
for_all_defaults(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri != no)
return prop;
}
return NULL;
}
struct property *sym_get_range_prop(struct symbol *sym)
{
struct property *prop;
for_all_properties(sym, prop, P_RANGE) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri != no)
return prop;
}
return NULL;
}
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
tristate tri;
/* any prompt visible? */
tri = no;
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
tri = E_OR(tri, prop->visible.tri);
}
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
tri = yes;
if (sym->visible != tri) {
sym->visible = tri;
sym_set_changed(sym);
}
if (sym_is_choice_value(sym))
return;
tri = no;
if (sym->rev_dep.expr)
tri = expr_calc_value(sym->rev_dep.expr);
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
tri = yes;
if (sym->rev_dep.tri != tri) {
sym->rev_dep.tri = tri;
sym_set_changed(sym);
}
}
static struct symbol *sym_calc_choice(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
/* is the user choice visible? */
def_sym = sym->user.val;
if (def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* any of the defaults visible? */
for_all_defaults(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
def_sym = prop_get_symbol(prop);
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* just get the first visible value */
prop = sym_get_choice_prop(sym);
for (e = prop->expr; e; e = e->left.expr) {
def_sym = e->right.sym;
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* no choice? reset tristate value */
sym->curr.tri = no;
return NULL;
}
void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
struct property *prop;
struct expr *e;
if (!sym)
return;
if (sym->flags & SYMBOL_VALID)
return;
sym->flags |= SYMBOL_VALID;
oldval = sym->curr;
switch (sym->type) {
case S_INT:
case S_HEX:
case S_STRING:
newval = symbol_empty.curr;
break;
case S_BOOLEAN:
case S_TRISTATE:
newval = symbol_no.curr;
break;
default:
sym->curr.val = sym->name;
sym->curr.tri = no;
return;
}
if (!sym_is_choice_value(sym))
sym->flags &= ~SYMBOL_WRITE;
sym_calc_visibility(sym);
/* set default if recursively called */
sym->curr = newval;
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
if (sym_is_choice_value(sym) && sym->visible == yes) {
prop = sym_get_choice_prop(sym);
newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
sym->flags |= SYMBOL_WRITE;
if (sym_has_value(sym))
newval.tri = sym->user.tri;
else if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym);
if (prop)
newval.tri = expr_calc_value(prop->expr);
}
newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
} else if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym);
if (prop) {
sym->flags |= SYMBOL_WRITE;
newval.tri = expr_calc_value(prop->expr);
}
}
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
newval.tri = yes;
break;
case S_STRING:
case S_HEX:
case S_INT:
if (sym->visible != no) {
sym->flags |= SYMBOL_WRITE;
if (sym_has_value(sym)) {
newval.val = sym->user.val;
break;
}
}
prop = sym_get_default_prop(sym);
if (prop) {
struct symbol *ds = prop_get_symbol(prop);
if (ds) {
sym->flags |= SYMBOL_WRITE;
sym_calc_value(ds);
newval.val = ds->curr.val;
}
}
break;
default:
;
}
sym->curr = newval;
if (sym_is_choice(sym) && newval.tri == yes)
sym->curr.val = sym_calc_choice(sym);
if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
sym_set_changed(sym);
if (modules_sym == sym)
modules_val = modules_sym->curr.tri;
if (sym_is_choice(sym)) {
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
prop = sym_get_choice_prop(sym);
for (e = prop->expr; e; e = e->left.expr) {
e->right.sym->flags |= flags;
if (flags & SYMBOL_CHANGED)
sym_set_changed(e->right.sym);
}
}
}
void sym_clear_all_valid(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym->flags &= ~SYMBOL_VALID;
sym_change_count++;
if (modules_sym)
sym_calc_value(modules_sym);
}
void sym_set_changed(struct symbol *sym)
{
struct property *prop;
sym->flags |= SYMBOL_CHANGED;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu)
prop->menu->flags |= MENU_CHANGED;
}
}
void sym_set_all_changed(void)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym_set_changed(sym);
}
bool sym_tristate_within_range(struct symbol *sym, tristate val)
{
int type = sym_get_type(sym);
if (sym->visible == no)
return false;
if (type != S_BOOLEAN && type != S_TRISTATE)
return false;
if (type == S_BOOLEAN && val == mod)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
}
bool sym_set_tristate_value(struct symbol *sym, tristate val)
{
tristate oldval = sym_get_tristate_value(sym);
if (oldval != val && !sym_tristate_within_range(sym, val))
return false;
if (sym->flags & SYMBOL_NEW) {
sym->flags &= ~SYMBOL_NEW;
sym_set_changed(sym);
}
if (sym_is_choice_value(sym) && val == yes) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
cs->user.val = sym;
cs->flags &= ~SYMBOL_NEW;
}
sym->user.tri = val;
if (oldval != val) {
sym_clear_all_valid();
if (sym == modules_sym)
sym_set_all_changed();
}
return true;
}
tristate sym_toggle_tristate_value(struct symbol *sym)
{
tristate oldval, newval;
oldval = newval = sym_get_tristate_value(sym);
do {
switch (newval) {
case no:
newval = mod;
break;
case mod:
newval = yes;
break;
case yes:
newval = no;
break;
}
if (sym_set_tristate_value(sym, newval))
break;
} while (oldval != newval);
return newval;
}
bool sym_string_valid(struct symbol *sym, const char *str)
{
signed char ch;
switch (sym->type) {
case S_STRING:
return true;
case S_INT:
ch = *str++;
if (ch == '-')
ch = *str++;
if (!isdigit(ch))
return false;
if (ch == '0' && *str != 0)
return false;
while ((ch = *str++)) {
if (!isdigit(ch))
return false;
}
return true;
case S_HEX:
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
str += 2;
ch = *str++;
do {
if (!isxdigit(ch))
return false;
} while ((ch = *str++));
return true;
case S_BOOLEAN:
case S_TRISTATE:
switch (str[0]) {
case 'y': case 'Y':
case 'm': case 'M':
case 'n': case 'N':
return true;
}
return false;
default:
return false;
}
}
bool sym_string_within_range(struct symbol *sym, const char *str)
{
struct property *prop;
int val;
switch (sym->type) {
case S_STRING:
return sym_string_valid(sym, str);
case S_INT:
if (!sym_string_valid(sym, str))
return false;
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 10);
return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
val <= strtol(prop->expr->right.sym->name, NULL, 10);
case S_HEX:
if (!sym_string_valid(sym, str))
return false;
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 16);
return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
val <= strtol(prop->expr->right.sym->name, NULL, 16);
case S_BOOLEAN:
case S_TRISTATE:
switch (str[0]) {
case 'y': case 'Y':
return sym_tristate_within_range(sym, yes);
case 'm': case 'M':
return sym_tristate_within_range(sym, mod);
case 'n': case 'N':
return sym_tristate_within_range(sym, no);
}
return false;
default:
return false;
}
}
bool sym_set_string_value(struct symbol *sym, const char *newval)
{
const char *oldval;
char *val;
int size;
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (newval[0]) {
case 'y': case 'Y':
return sym_set_tristate_value(sym, yes);
case 'm': case 'M':
return sym_set_tristate_value(sym, mod);
case 'n': case 'N':
return sym_set_tristate_value(sym, no);
}
return false;
default:
;
}
if (!sym_string_within_range(sym, newval))
return false;
if (sym->flags & SYMBOL_NEW) {
sym->flags &= ~SYMBOL_NEW;
sym_set_changed(sym);
}
oldval = sym->user.val;
size = strlen(newval) + 1;
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
size += 2;
sym->user.val = val = malloc(size);
*val++ = '0';
*val++ = 'x';
} else if (!oldval || strcmp(oldval, newval))
sym->user.val = val = malloc(size);
else
return true;
strcpy(val, newval);
free((void *)oldval);
sym_clear_all_valid();
return true;
}
const char *sym_get_string_value(struct symbol *sym)
{
tristate val;
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
val = sym_get_tristate_value(sym);
switch (val) {
case no:
return "n";
case mod:
return "m";
case yes:
return "y";
}
break;
default:
;
}
return (const char *)sym->curr.val;
}
bool sym_is_changable(struct symbol *sym)
{
return sym->visible > sym->rev_dep.tri;
}
struct symbol *sym_lookup(const char *name, int isconst)
{
struct symbol *symbol;
const char *ptr;
char *new_name;
int hash = 0;
if (name) {
if (name[0] && !name[1]) {
switch (name[0]) {
case 'y': return &symbol_yes;
case 'm': return &symbol_mod;
case 'n': return &symbol_no;
}
}
for (ptr = name; *ptr; ptr++)
hash += *ptr;
hash &= 0xff;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name)) {
if ((isconst && symbol->flags & SYMBOL_CONST) ||
(!isconst && !(symbol->flags & SYMBOL_CONST)))
return symbol;
}
}
new_name = strdup(name);
} else {
new_name = NULL;
hash = 256;
}
symbol = malloc(sizeof(*symbol));
memset(symbol, 0, sizeof(*symbol));
symbol->name = new_name;
symbol->type = S_UNKNOWN;
symbol->flags = SYMBOL_NEW;
if (isconst)
symbol->flags |= SYMBOL_CONST;
symbol->next = symbol_hash[hash];
symbol_hash[hash] = symbol;
return symbol;
}
struct symbol *sym_find(const char *name)
{
struct symbol *symbol = NULL;
const char *ptr;
int hash = 0;
if (!name)
return NULL;
if (name[0] && !name[1]) {
switch (name[0]) {
case 'y': return &symbol_yes;
case 'm': return &symbol_mod;
case 'n': return &symbol_no;
}
}
for (ptr = name; *ptr; ptr++)
hash += *ptr;
hash &= 0xff;
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name) &&
!(symbol->flags & SYMBOL_CONST))
break;
}
return symbol;
}
struct symbol **sym_re_search(const char *pattern)
{
struct symbol *sym, **sym_arr = NULL;
int i, cnt, size;
regex_t re;
cnt = size = 0;
/* Skip if empty */
if (strlen(pattern) == 0)
return NULL;
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
return NULL;
for_all_symbols(i, sym) {
if (sym->flags & SYMBOL_CONST || !sym->name)
continue;
if (regexec(&re, sym->name, 0, NULL, 0))
continue;
if (cnt + 1 >= size) {
void *tmp = sym_arr;
size += 16;
sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
if (!sym_arr) {
free(tmp);
return NULL;
}
}
sym_arr[cnt++] = sym;
}
if (sym_arr)
sym_arr[cnt] = NULL;
regfree(&re);
return sym_arr;
}
struct symbol *sym_check_deps(struct symbol *sym);
static struct symbol *sym_check_expr_deps(struct expr *e)
{
struct symbol *sym;
if (!e)
return NULL;
switch (e->type) {
case E_OR:
case E_AND:
sym = sym_check_expr_deps(e->left.expr);
if (sym)
return sym;
return sym_check_expr_deps(e->right.expr);
case E_NOT:
return sym_check_expr_deps(e->left.expr);
case E_EQUAL:
case E_UNEQUAL:
sym = sym_check_deps(e->left.sym);
if (sym)
return sym;
return sym_check_deps(e->right.sym);
case E_SYMBOL:
return sym_check_deps(e->left.sym);
default:
break;
}
printf("Oops! How to check %d?\n", e->type);
return NULL;
}
struct symbol *sym_check_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
if (sym->flags & SYMBOL_CHECK_DONE)
return NULL;
if (sym->flags & SYMBOL_CHECK) {
printf("Warning! Found recursive dependency: %s", sym->name);
return sym;
}
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
goto out;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->type == P_CHOICE || prop->type == P_SELECT)
continue;
sym2 = sym_check_expr_deps(prop->visible.expr);
if (sym2)
goto out;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
goto out;
}
out:
if (sym2)
printf(" %s", sym->name);
sym->flags &= ~SYMBOL_CHECK;
return sym2;
}
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
{
struct property *prop;
struct property **propp;
prop = malloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
prop->sym = sym;
prop->file = current_file;
prop->lineno = zconf_lineno();
/* append property to the prop list of symbol */
if (sym) {
for (propp = &sym->prop; *propp; propp = &(*propp)->next)
;
*propp = prop;
}
return prop;
}
struct symbol *prop_get_symbol(struct property *prop)
{
if (prop->expr && (prop->expr->type == E_SYMBOL ||
prop->expr->type == E_CHOICE))
return prop->expr->left.sym;
return NULL;
}
const char *prop_get_type_name(enum prop_type type)
{
switch (type) {
case P_PROMPT:
return "prompt";
case P_COMMENT:
return "comment";
case P_MENU:
return "menu";
case P_DEFAULT:
return "default";
case P_CHOICE:
return "choice";
case P_SELECT:
return "select";
case P_RANGE:
return "range";
case P_UNKNOWN:
break;
}
return "unknown";
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
* Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
*
* Released under the terms of the GNU GPL v2.0.
*/
#include <string.h>
#include "lkc.h"
/* file already present in list? If not add it */
struct file *file_lookup(const char *name)
{
struct file *file;
for (file = file_list; file; file = file->next) {
if (!strcmp(name, file->name))
return file;
}
file = malloc(sizeof(*file));
memset(file, 0, sizeof(*file));
file->name = strdup(name);
file->next = file_list;
file_list = file;
return file;
}
/* write a dependency file as used by kbuild to track dependencies */
int file_write_dep(const char *name)
{
struct file *file;
FILE *out;
if (!name)
name = "config/.config.cmd";
out = fopen("config/.config.tmp", "w");
if (!out)
return 1;
fprintf(out, "deps_config := \\\n");
for (file = file_list; file; file = file->next) {
if (file->next)
fprintf(out, "\t%s \\\n", file->name);
else
fprintf(out, "\t%s\n", file->name);
}
fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
fclose(out);
rename(".config.tmp", name);
return 0;
}
/* Allocate initial growable sting */
struct gstr str_new(void)
{
struct gstr gs;
gs.s = malloc(sizeof(char) * 64);
gs.len = 16;
strcpy(gs.s, "\0");
return gs;
}
/* Allocate and assign growable string */
struct gstr str_assign(const char *s)
{
struct gstr gs;
gs.s = strdup(s);
gs.len = strlen(s) + 1;
return gs;
}
/* Free storage for growable string */
void str_free(struct gstr *gs)
{
if (gs->s)
free(gs->s);
gs->s = NULL;
gs->len = 0;
}
/* Append to growable string */
void str_append(struct gstr *gs, const char *s)
{
size_t l = strlen(gs->s) + strlen(s) + 1;
if (l > gs->len) {
gs->s = realloc(gs->s, l);
gs->len = l;
}
strcat(gs->s, s);
}
/* Append printf formatted string to growable string */
void str_printf(struct gstr *gs, const char *fmt, ...)
{
va_list ap;
char s[10000]; /* big enough... */
va_start(ap, fmt);
vsnprintf(s, sizeof(s), fmt, ap);
str_append(gs, s);
va_end(ap);
}
/* Retreive value of growable string */
const char *str_get(struct gstr *gs)
{
return gs->s;
}

View File

@ -0,0 +1,366 @@
%option backup nostdinit noyywrap never-interactive full ecs
%option 8bit backup nodefault perf-report perf-report
%x COMMAND HELP STRING PARAM
%{
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
#define START_STRSIZE 16
char *text;
static char *text_ptr;
static int text_size, text_asize;
struct buffer {
struct buffer *parent;
YY_BUFFER_STATE state;
};
struct buffer *current_buf;
static int last_ts, first_ts;
static void zconf_endhelp(void);
static struct buffer *zconf_endfile(void);
void new_string(void)
{
text = malloc(START_STRSIZE);
text_asize = START_STRSIZE;
text_ptr = text;
text_size = 0;
*text_ptr = 0;
}
void append_string(const char *str, int size)
{
int new_size = text_size + size + 1;
if (new_size > text_asize) {
text = realloc(text, new_size);
text_asize = new_size;
text_ptr = text + text_size;
}
memcpy(text_ptr, str, size);
text_ptr += size;
text_size += size;
*text_ptr = 0;
}
void alloc_string(const char *str, int size)
{
text = malloc(size + 1);
memcpy(text, str, size);
text[size] = 0;
}
%}
ws [ \n\t]
n [A-Za-z0-9_]
%%
int str = 0;
int ts, i;
[ \t]*#.*\n current_file->lineno++;
[ \t]*#.*
[ \t]*\n current_file->lineno++; return T_EOL;
[ \t]+ {
BEGIN(COMMAND);
}
. {
unput(yytext[0]);
BEGIN(COMMAND);
}
<COMMAND>{
"mainmenu" BEGIN(PARAM); return T_MAINMENU;
"menu" BEGIN(PARAM); return T_MENU;
"endmenu" BEGIN(PARAM); return T_ENDMENU;
"source" BEGIN(PARAM); return T_SOURCE;
"choice" BEGIN(PARAM); return T_CHOICE;
"endchoice" BEGIN(PARAM); return T_ENDCHOICE;
"comment" BEGIN(PARAM); return T_COMMENT;
"config" BEGIN(PARAM); return T_CONFIG;
"menuconfig" BEGIN(PARAM); return T_MENUCONFIG;
"help" BEGIN(PARAM); return T_HELP;
"if" BEGIN(PARAM); return T_IF;
"endif" BEGIN(PARAM); return T_ENDIF;
"depends" BEGIN(PARAM); return T_DEPENDS;
"requires" BEGIN(PARAM); return T_REQUIRES;
"optional" BEGIN(PARAM); return T_OPTIONAL;
"default" BEGIN(PARAM); return T_DEFAULT;
"prompt" BEGIN(PARAM); return T_PROMPT;
"tristate" BEGIN(PARAM); return T_TRISTATE;
"def_tristate" BEGIN(PARAM); return T_DEF_TRISTATE;
"bool" BEGIN(PARAM); return T_BOOLEAN;
"boolean" BEGIN(PARAM); return T_BOOLEAN;
"def_bool" BEGIN(PARAM); return T_DEF_BOOLEAN;
"def_boolean" BEGIN(PARAM); return T_DEF_BOOLEAN;
"int" BEGIN(PARAM); return T_INT;
"hex" BEGIN(PARAM); return T_HEX;
"string" BEGIN(PARAM); return T_STRING;
"select" BEGIN(PARAM); return T_SELECT;
"enable" BEGIN(PARAM); return T_SELECT;
"range" BEGIN(PARAM); return T_RANGE;
{n}+ {
alloc_string(yytext, yyleng);
zconflval.string = text;
return T_WORD;
}
.
\n current_file->lineno++; BEGIN(INITIAL);
}
<PARAM>{
"&&" return T_AND;
"||" return T_OR;
"(" return T_OPEN_PAREN;
")" return T_CLOSE_PAREN;
"!" return T_NOT;
"=" return T_EQUAL;
"!=" return T_UNEQUAL;
"if" return T_IF;
"on" return T_ON;
\"|\' {
str = yytext[0];
new_string();
BEGIN(STRING);
}
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
--- /* ignore */
({n}|[-/.])+ {
alloc_string(yytext, yyleng);
zconflval.string = text;
return T_WORD;
}
#.* /* comment */
\\\n current_file->lineno++;
.
<<EOF>> {
BEGIN(INITIAL);
}
}
<STRING>{
[^'"\\\n]+/\n {
append_string(yytext, yyleng);
zconflval.string = text;
return T_WORD_QUOTE;
}
[^'"\\\n]+ {
append_string(yytext, yyleng);
}
\\.?/\n {
append_string(yytext + 1, yyleng - 1);
zconflval.string = text;
return T_WORD_QUOTE;
}
\\.? {
append_string(yytext + 1, yyleng - 1);
}
\'|\" {
if (str == yytext[0]) {
BEGIN(PARAM);
zconflval.string = text;
return T_WORD_QUOTE;
} else
append_string(yytext, 1);
}
\n {
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
current_file->lineno++;
BEGIN(INITIAL);
return T_EOL;
}
<<EOF>> {
BEGIN(INITIAL);
}
}
<HELP>{
[ \t]+ {
ts = 0;
for (i = 0; i < yyleng; i++) {
if (yytext[i] == '\t')
ts = (ts & ~7) + 8;
else
ts++;
}
last_ts = ts;
if (first_ts) {
if (ts < first_ts) {
zconf_endhelp();
return T_HELPTEXT;
}
ts -= first_ts;
while (ts > 8) {
append_string(" ", 8);
ts -= 8;
}
append_string(" ", ts);
}
}
[ \t]*\n/[^ \t\n] {
current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
}
[ \t]*\n {
current_file->lineno++;
append_string("\n", 1);
}
[^ \t\n].* {
append_string(yytext, yyleng);
if (!first_ts)
first_ts = last_ts;
}
<<EOF>> {
zconf_endhelp();
return T_HELPTEXT;
}
}
<<EOF>> {
if (current_buf) {
zconf_endfile();
return T_EOF;
}
fclose(yyin);
yyterminate();
}
%%
void zconf_starthelp(void)
{
new_string();
last_ts = first_ts = 0;
BEGIN(HELP);
}
static void zconf_endhelp(void)
{
zconflval.string = text;
BEGIN(INITIAL);
}
/*
* Try to open specified file with following names:
* ./name
* $(srctree)/name
* The latter is used when srctree is separate from objtree
* when compiling the kernel.
* Return NULL if file is not found.
*/
FILE *zconf_fopen(const char *name)
{
char *env, fullname[PATH_MAX+1];
FILE *f;
f = fopen(name, "r");
if (!f && name[0] != '/') {
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
f = fopen(fullname, "r");
}
}
return f;
}
void zconf_initscan(const char *name)
{
yyin = zconf_fopen(name);
if (!yyin) {
printf("can't find file %s\n", name);
exit(1);
}
current_buf = malloc(sizeof(*current_buf));
memset(current_buf, 0, sizeof(*current_buf));
current_file = file_lookup(name);
current_file->lineno = 1;
current_file->flags = FILE_BUSY;
}
void zconf_nextfile(const char *name)
{
struct file *file = file_lookup(name);
struct buffer *buf = malloc(sizeof(*buf));
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
yyin = zconf_fopen(name);
if (!yyin) {
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
exit(1);
}
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
buf->parent = current_buf;
current_buf = buf;
if (file->flags & FILE_BUSY) {
printf("recursive scan (%s)?\n", name);
exit(1);
}
if (file->flags & FILE_SCANNED) {
printf("file %s already scanned?\n", name);
exit(1);
}
file->flags |= FILE_BUSY;
file->lineno = 1;
file->parent = current_file;
current_file = file;
}
static struct buffer *zconf_endfile(void)
{
struct buffer *parent;
current_file->flags |= FILE_SCANNED;
current_file->flags &= ~FILE_BUSY;
current_file = current_file->parent;
parent = current_buf->parent;
if (parent) {
fclose(yyin);
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(parent->state);
}
free(current_buf);
current_buf = parent;
return parent;
}
int zconf_lineno(void)
{
if (current_buf)
return current_file->lineno - 1;
else
return 0;
}
char *zconf_curname(void)
{
if (current_buf)
return current_file->name;
else
return "<none>";
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,125 @@
/* A Bison parser, made from zconf.y, by GNU bison 1.75. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
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, 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. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
#ifndef BISON_ZCONF_TAB_H
# define BISON_ZCONF_TAB_H
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
T_MAINMENU = 258,
T_MENU = 259,
T_ENDMENU = 260,
T_SOURCE = 261,
T_CHOICE = 262,
T_ENDCHOICE = 263,
T_COMMENT = 264,
T_CONFIG = 265,
T_HELP = 266,
T_HELPTEXT = 267,
T_IF = 268,
T_ENDIF = 269,
T_DEPENDS = 270,
T_REQUIRES = 271,
T_OPTIONAL = 272,
T_PROMPT = 273,
T_DEFAULT = 274,
T_TRISTATE = 275,
T_BOOLEAN = 276,
T_INT = 277,
T_HEX = 278,
T_WORD = 279,
T_STRING = 280,
T_UNEQUAL = 281,
T_EOF = 282,
T_EOL = 283,
T_CLOSE_PAREN = 284,
T_OPEN_PAREN = 285,
T_ON = 286,
T_OR = 287,
T_AND = 288,
T_EQUAL = 289,
T_NOT = 290
};
#endif
#define T_MAINMENU 258
#define T_MENU 259
#define T_ENDMENU 260
#define T_SOURCE 261
#define T_CHOICE 262
#define T_ENDCHOICE 263
#define T_COMMENT 264
#define T_CONFIG 265
#define T_HELP 266
#define T_HELPTEXT 267
#define T_IF 268
#define T_ENDIF 269
#define T_DEPENDS 270
#define T_REQUIRES 271
#define T_OPTIONAL 272
#define T_PROMPT 273
#define T_DEFAULT 274
#define T_TRISTATE 275
#define T_BOOLEAN 276
#define T_INT 277
#define T_HEX 278
#define T_WORD 279
#define T_STRING 280
#define T_UNEQUAL 281
#define T_EOF 282
#define T_EOL 283
#define T_CLOSE_PAREN 284
#define T_OPEN_PAREN 285
#define T_ON 286
#define T_OR 287
#define T_AND 288
#define T_EQUAL 289
#define T_NOT 290
#ifndef YYSTYPE
#line 33 "zconf.y"
typedef union {
int token;
char *string;
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
} yystype;
/* Line 1281 of /usr/share/bison/yacc.c. */
#line 118 "zconf.tab.h"
# define YYSTYPE yystype
#endif
extern YYSTYPE zconflval;
#endif /* not BISON_ZCONF_TAB_H */

View File

@ -0,0 +1,690 @@
%{
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
#define PRINTD 0x0001
#define DEBUG_PARSE 0x0002
int cdebug = PRINTD;
extern int zconflex(void);
static void zconfprint(const char *err, ...);
static void zconferror(const char *err);
static bool zconf_endtoken(int token, int starttoken, int endtoken);
struct symbol *symbol_hash[257];
static struct menu *current_menu, *current_entry;
#define YYERROR_VERBOSE
%}
%expect 40
%union
{
int token;
char *string;
struct symbol *symbol;
struct expr *expr;
struct menu *menu;
}
%token T_MAINMENU
%token T_MENU
%token T_ENDMENU
%token T_SOURCE
%token T_CHOICE
%token T_ENDCHOICE
%token T_COMMENT
%token T_CONFIG
%token T_MENUCONFIG
%token T_HELP
%token <string> T_HELPTEXT
%token T_IF
%token T_ENDIF
%token T_DEPENDS
%token T_REQUIRES
%token T_OPTIONAL
%token T_PROMPT
%token T_DEFAULT
%token T_TRISTATE
%token T_DEF_TRISTATE
%token T_BOOLEAN
%token T_DEF_BOOLEAN
%token T_STRING
%token T_INT
%token T_HEX
%token <string> T_WORD
%token <string> T_WORD_QUOTE
%token T_UNEQUAL
%token T_EOF
%token T_EOL
%token T_CLOSE_PAREN
%token T_OPEN_PAREN
%token T_ON
%token T_SELECT
%token T_RANGE
%left T_OR
%left T_AND
%left T_EQUAL T_UNEQUAL
%nonassoc T_NOT
%type <string> prompt
%type <string> source
%type <symbol> symbol
%type <expr> expr
%type <expr> if_expr
%type <token> end
%{
#define LKC_DIRECT_LINK
#include "lkc.h"
%}
%%
input: /* empty */
| input block
;
block: common_block
| choice_stmt
| menu_stmt
| T_MAINMENU prompt nl_or_eof
| T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); }
| T_ENDIF { zconfprint("unexpected 'endif' statement"); }
| T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); }
| error nl_or_eof { zconfprint("syntax error"); yyerrok; }
;
common_block:
if_stmt
| comment_stmt
| config_stmt
| menuconfig_stmt
| source_stmt
| nl_or_eof
;
/* config/menuconfig entry */
config_entry_start: T_CONFIG T_WORD T_EOL
{
struct symbol *sym = sym_lookup($2, 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
};
config_stmt: config_entry_start config_option_list
{
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
};
menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
{
struct symbol *sym = sym_lookup($2, 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
};
menuconfig_stmt: menuconfig_entry_start config_option_list
{
if (current_entry->prompt)
current_entry->prompt->type = P_MENU;
else
zconfprint("warning: menuconfig statement without prompt");
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
};
config_option_list:
/* empty */
| config_option_list config_option
| config_option_list depends
| config_option_list help
| config_option_list T_EOL
;
config_option: T_TRISTATE prompt_stmt_opt T_EOL
{
menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
};
config_option: T_DEF_TRISTATE expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
};
config_option: T_BOOLEAN prompt_stmt_opt T_EOL
{
menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
};
config_option: T_DEF_BOOLEAN expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
};
config_option: T_INT prompt_stmt_opt T_EOL
{
menu_set_type(S_INT);
printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
};
config_option: T_HEX prompt_stmt_opt T_EOL
{
menu_set_type(S_HEX);
printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
};
config_option: T_STRING prompt_stmt_opt T_EOL
{
menu_set_type(S_STRING);
printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
};
config_option: T_PROMPT prompt if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
};
config_option: T_DEFAULT expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
};
config_option: T_SELECT T_WORD if_expr T_EOL
{
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
};
config_option: T_RANGE symbol symbol if_expr T_EOL
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
};
/* choice entry */
choice: T_CHOICE T_EOL
{
struct symbol *sym = sym_lookup(NULL, 0);
sym->flags |= SYMBOL_CHOICE;
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
};
choice_entry: choice choice_option_list
{
menu_end_entry();
menu_add_menu();
};
choice_end: end
{
if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
};
choice_stmt:
choice_entry choice_block choice_end
| choice_entry choice_block
{
printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
zconfnerrs++;
};
choice_option_list:
/* empty */
| choice_option_list choice_option
| choice_option_list depends
| choice_option_list help
| choice_option_list T_EOL
;
choice_option: T_PROMPT prompt if_expr T_EOL
{
menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
};
choice_option: T_TRISTATE prompt_stmt_opt T_EOL
{
menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
};
choice_option: T_BOOLEAN prompt_stmt_opt T_EOL
{
menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
};
choice_option: T_OPTIONAL T_EOL
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
};
choice_option: T_DEFAULT T_WORD if_expr T_EOL
{
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
};
choice_block:
/* empty */
| choice_block common_block
;
/* if entry */
if: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
menu_add_dep($2);
menu_end_entry();
menu_add_menu();
};
if_end: end
{
if (zconf_endtoken($1, T_IF, T_ENDIF)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
};
if_stmt:
if if_block if_end
| if if_block
{
printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
zconfnerrs++;
};
if_block:
/* empty */
| if_block common_block
| if_block menu_stmt
| if_block choice_stmt
;
/* menu entry */
menu: T_MENU prompt T_EOL
{
menu_add_entry(NULL);
menu_add_prop(P_MENU, $2, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
};
menu_entry: menu depends_list
{
menu_end_entry();
menu_add_menu();
};
menu_end: end
{
if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
};
menu_stmt:
menu_entry menu_block menu_end
| menu_entry menu_block
{
printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
zconfnerrs++;
};
menu_block:
/* empty */
| menu_block common_block
| menu_block menu_stmt
| menu_block choice_stmt
| menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
;
source: T_SOURCE prompt T_EOL
{
$$ = $2;
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
};
source_stmt: source
{
zconf_nextfile($1);
};
/* comment entry */
comment: T_COMMENT prompt T_EOL
{
menu_add_entry(NULL);
menu_add_prop(P_COMMENT, $2, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
};
comment_stmt: comment depends_list
{
menu_end_entry();
};
/* help option */
help_start: T_HELP T_EOL
{
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
zconf_starthelp();
};
help: help_start T_HELPTEXT
{
current_entry->sym->help = $2;
};
/* depends option */
depends_list: /* empty */
| depends_list depends
| depends_list T_EOL
;
depends: T_DEPENDS T_ON expr T_EOL
{
menu_add_dep($3);
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
}
| T_DEPENDS expr T_EOL
{
menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
}
| T_REQUIRES expr T_EOL
{
menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
};
/* prompt statement */
prompt_stmt_opt:
/* empty */
| prompt if_expr
{
menu_add_prop(P_PROMPT, $1, NULL, $2);
};
prompt: T_WORD
| T_WORD_QUOTE
;
end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; }
| T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; }
| T_ENDIF nl_or_eof { $$ = T_ENDIF; }
;
nl_or_eof:
T_EOL | T_EOF;
if_expr: /* empty */ { $$ = NULL; }
| T_IF expr { $$ = $2; }
;
expr: symbol { $$ = expr_alloc_symbol($1); }
| symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
| symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
| T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
| T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
| expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
;
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
| T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
;
%%
void conf_parse(const char *name)
{
struct symbol *sym;
int i;
zconf_initscan(name);
sym_init();
menu_init();
modules_sym = sym_lookup("MODULES", 0);
rootmenu.prompt = menu_add_prop(P_MENU, "axTLS Configuration", NULL, NULL);
//zconfdebug = 1;
zconfparse();
if (zconfnerrs)
exit(1);
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
printf("\n");
else
sym->flags |= SYMBOL_CHECK_DONE;
}
sym_change_count = 1;
}
const char *zconf_tokenname(int token)
{
switch (token) {
case T_MENU: return "menu";
case T_ENDMENU: return "endmenu";
case T_CHOICE: return "choice";
case T_ENDCHOICE: return "endchoice";
case T_IF: return "if";
case T_ENDIF: return "endif";
}
return "<token>";
}
static bool zconf_endtoken(int token, int starttoken, int endtoken)
{
if (token != endtoken) {
zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
zconfnerrs++;
return false;
}
if (current_menu->file != current_file) {
zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
zconfprint("location of the '%s'", zconf_tokenname(starttoken));
zconfnerrs++;
return false;
}
return true;
}
static void zconfprint(const char *err, ...)
{
va_list ap;
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
va_start(ap, err);
vfprintf(stderr, err, ap);
va_end(ap);
fprintf(stderr, "\n");
}
static void zconferror(const char *err)
{
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
}
void print_quoted_string(FILE *out, const char *str)
{
const char *p;
int len;
putc('"', out);
while ((p = strchr(str, '"'))) {
len = p - str;
if (len)
fprintf(out, "%.*s", len, str);
fputs("\\\"", out);
str = p + 1;
}
fputs(str, out);
putc('"', out);
}
void print_symbol(FILE *out, struct menu *menu)
{
struct symbol *sym = menu->sym;
struct property *prop;
if (sym_is_choice(sym))
fprintf(out, "choice\n");
else
fprintf(out, "config %s\n", sym->name);
switch (sym->type) {
case S_BOOLEAN:
fputs(" boolean\n", out);
break;
case S_TRISTATE:
fputs(" tristate\n", out);
break;
case S_STRING:
fputs(" string\n", out);
break;
case S_INT:
fputs(" integer\n", out);
break;
case S_HEX:
fputs(" hex\n", out);
break;
default:
fputs(" ???\n", out);
break;
}
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu != menu)
continue;
switch (prop->type) {
case P_PROMPT:
fputs(" prompt ", out);
print_quoted_string(out, prop->text);
if (!expr_is_yes(prop->visible.expr)) {
fputs(" if ", out);
expr_fprint(prop->visible.expr, out);
}
fputc('\n', out);
break;
case P_DEFAULT:
fputs( " default ", out);
expr_fprint(prop->expr, out);
if (!expr_is_yes(prop->visible.expr)) {
fputs(" if ", out);
expr_fprint(prop->visible.expr, out);
}
fputc('\n', out);
break;
case P_CHOICE:
fputs(" #choice value\n", out);
break;
default:
fprintf(out, " unknown prop %d!\n", prop->type);
break;
}
}
if (sym->help) {
int len = strlen(sym->help);
while (sym->help[--len] == '\n')
sym->help[len] = 0;
fprintf(out, " help\n%s\n", sym->help);
}
fputc('\n', out);
}
void zconfdump(FILE *out)
{
struct property *prop;
struct symbol *sym;
struct menu *menu;
menu = rootmenu.list;
while (menu) {
if ((sym = menu->sym))
print_symbol(out, menu);
else if ((prop = menu->prompt)) {
switch (prop->type) {
case P_COMMENT:
fputs("\ncomment ", out);
print_quoted_string(out, prop->text);
fputs("\n", out);
break;
case P_MENU:
fputs("\nmenu ", out);
print_quoted_string(out, prop->text);
fputs("\n", out);
break;
default:
;
}
if (!expr_is_yes(prop->visible.expr)) {
fputs(" depends ", out);
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
fputs("\n", out);
}
if (menu->list)
menu = menu->list;
else if (menu->next)
menu = menu->next;
else while ((menu = menu->parent)) {
if (menu->prompt && menu->prompt->type == P_MENU)
fputs("\nendmenu\n", out);
if (menu->next) {
menu = menu->next;
break;
}
}
}
}
#include "lex.zconf.c"
#include "util.c"
#include "confdata.c"
#include "expr.c"
#include "symbol.c"
#include "menu.c"

116
config/win32config Normal file
View File

@ -0,0 +1,116 @@
#
# Automatically generated make config: don't edit
#
HAVE_DOT_CONFIG=y
# CONFIG_PLATFORM_LINUX is not set
# CONFIG_PLATFORM_CYGWIN is not set
# CONFIG_PLATFORM_SOLARIS is not set
CONFIG_PLATFORM_WIN32=y
#
# General Configuration
#
PREFIX=""
# CONFIG_DEBUG is not set
#
# Microsoft Compiler Options
#
# CONFIG_VISUAL_STUDIO_6_0 is not set
CONFIG_VISUAL_STUDIO_7_0=y
# CONFIG_VISUAL_STUDIO_8_0 is not set
CONFIG_VISUAL_STUDIO_6_0_BASE=""
CONFIG_VISUAL_STUDIO_7_0_BASE="c:\\Program Files\\Microsoft Visual Studio .NET 2003"
CONFIG_VISUAL_STUDIO_8_0_BASE=""
CONFIG_EXTRA_CFLAGS_OPTIONS=""
CONFIG_EXTRA_LDFLAGS_OPTIONS=""
#
# SSL Library
#
# CONFIG_SSL_SERVER_ONLY is not set
# CONFIG_SSL_CERT_VERIFICATION is not set
# CONFIG_SSL_ENABLE_CLIENT is not set
CONFIG_SSL_FULL_MODE=y
# CONFIG_SSL_SKELETON_MODE is not set
# CONFIG_SSL_PROT_LOW is not set
CONFIG_SSL_PROT_MEDIUM=y
# CONFIG_SSL_PROT_HIGH is not set
CONFIG_SSL_USE_DEFAULT_KEY=y
CONFIG_SSL_ENABLE_V23_HANDSHAKE=y
CONFIG_SSL_HAS_PEM=y
CONFIG_SSL_USE_PKCS12=y
CONFIG_SSL_EXPIRY_TIME=24
CONFIG_X509_MAX_CA_CERTS=4
CONFIG_SSL_MAX_CERTS=2
# CONFIG_SSL_CTX_MUTEXING is not set
# CONFIG_USE_DEV_URANDOM is not set
CONFIG_WIN32_USE_CRYPTO_LIB=y
# CONFIG_PERFORMANCE_TESTING is not set
# CONFIG_SSL_TEST is not set
CONFIG_AXHTTPD=y
#
# Axhttpd Configuration
#
# CONFIG_HTTP_STATIC_BUILD is not set
CONFIG_HTTP_PORT=80
CONFIG_HTTP_HTTPS_PORT=443
CONFIG_HTTP_SESSION_CACHE_SIZE=5
CONFIG_HTTP_WEBROOT="www"
CONFIG_HTTP_TIMEOUT=300
# CONFIG_HTTP_HAS_CGI is not set
CONFIG_HTTP_CGI_EXTENSIONS=""
CONFIG_HTTP_DIRECTORIES=y
# CONFIG_HTTP_USE_CHROOT is not set
# CONFIG_HTTP_CHANGE_UID is not set
CONFIG_HTTP_HAS_AUTHORIZATION=y
# CONFIG_HTTP_HAS_IPV6 is not set
CONFIG_HTTP_ALL_MIME_TYPES=y
CONFIG_HTTP_VERBOSE=y
# CONFIG_HTTP_IS_DAEMON is not set
#
# Language Bindings
#
CONFIG_BINDINGS=y
CONFIG_CSHARP_BINDINGS=y
CONFIG_VBNET_BINDINGS=y
#
# .Net Framework
#
CONFIG_DOT_NET_FRAMEWORK_BASE="c:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727"
CONFIG_JAVA_BINDINGS=y
#
# Java Home
#
CONFIG_JAVA_HOME="c:\\Program Files\\Java\\jdk1.5.0_06"
# CONFIG_PERL_BINDINGS is not set
CONFIG_PERL_CORE=""
CONFIG_PERL_LIB=""
#
# Samples
#
CONFIG_SAMPLES=y
CONFIG_C_SAMPLES=y
CONFIG_CSHARP_SAMPLES=y
CONFIG_VBNET_SAMPLES=y
CONFIG_JAVA_SAMPLES=y
# CONFIG_PERL_SAMPLES is not set
#
# BigInt Options
#
# CONFIG_BIGINT_CLASSICAL is not set
# CONFIG_BIGINT_MONTGOMERY is not set
CONFIG_BIGINT_BARRETT=y
CONFIG_BIGINT_CRT=y
# CONFIG_BIGINT_KARATSUBA is not set
MUL_KARATSUBA_THRESH=0
SQU_KARATSUBA_THRESH=0
CONFIG_BIGINT_SLIDING_WINDOW=y
CONFIG_BIGINT_SQUARE=y
# CONFIG_BIGINT_CHECK_ON is not set

27
docsrc/Makefile Normal file
View File

@ -0,0 +1,27 @@
#
# Copyright(C) 2006 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This license 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 Lesser General Public License
# along with this license; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
include ../config/makefile.conf
all:
doco:
doxygen ./axTLS.dox
clean::
@-rm -fr html *~

1237
docsrc/axTLS.dox Normal file

File diff suppressed because it is too large Load Diff

3
docsrc/doco_footer.html Normal file
View File

@ -0,0 +1,3 @@
<p></p>
<p align="center"><img src="../images/tsbasbw.gif" width="1000" height="7"></p>
<CITE>Copyright <sup>©</sup> 2007 Cameron Rich</CITE>

BIN
docsrc/images/axolotl.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
docsrc/images/tsbasbw.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

138
httpd/Config.in Normal file
View File

@ -0,0 +1,138 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "Axhttpd Configuration"
depends on CONFIG_AXHTTPD
config CONFIG_HTTP_STATIC_BUILD
bool "Static Build"
default n
help
Select y if you want axhttpd to be a static build (i.e. don't use the
axtls shared library or dll).
config CONFIG_HTTP_PORT
int "HTTP port"
default 80
help
The port number of the normal HTTP server.
You must be a root user in order to use the default port.
config CONFIG_HTTP_HTTPS_PORT
int "HTTPS port"
default 443
help
The port number of the HTTPS server.
You must be a root user in order to use the default port.
config CONFIG_HTTP_SESSION_CACHE_SIZE
int "SSL session cache size"
default 5
help
The size of the SSL session cache.
This is not actually related to the number of concurrent users, but
for optimum performance they should be the same (with a penalty
in memory usage).
config CONFIG_HTTP_WEBROOT
string "Web root location"
default "../www" if !CONFIG_PLATFORM_WIN32
default "..\\www" if CONFIG_PLATFORM_WIN32
help
The location of the web root in relation to axhttpd. This is
the directory where index.html lives.
config CONFIG_HTTP_TIMEOUT
int "Timeout"
default 300
help
Set the timeout of a connection in seconds.
config CONFIG_HTTP_HAS_CGI
bool "Enable CGI"
default n
help
Enable the CGI capability.
config CONFIG_HTTP_CGI_EXTENSIONS
string "CGI File Extension(s)"
default ".php,.sh"
depends on CONFIG_HTTP_HAS_CGI
help
Tell axhhtpd what file extension(s) are used for CGI.
This is a comma separated list.
config CONFIG_HTTP_DIRECTORIES
bool "Enable Directory Listing"
default n
help
Enable directory listing.
config CONFIG_HTTP_HAS_AUTHORIZATION
bool "Enable authorization"
default n
help
Pages/directories can have passwords associated with them.
config CONFIG_HTTP_USE_CHROOT
bool "Use chroot()"
default n
depends on !CONFIG_PLATFORM_WIN32
help
Use chroot() to switch directories with a certain degree of
protection. However access to /bin and /lib have to replaced with
duplicate binaries.
This feature is normally disabled.
config CONFIG_HTTP_CHANGE_UID
bool "Change UID"
default n
depends on !CONFIG_PLATFORM_WIN32
help
Call setgid()/setuid() to disable access to protected files.
This feature is normally disabled.
config CONFIG_HTTP_HAS_IPV6
bool "Enable IPv6"
default n
depends on !CONFIG_PLATFORM_WIN32
help
Use IPv6 instead of IPv4.
Does not work under Win32
config CONFIG_HTTP_ALL_MIME_TYPES
bool "Use all mime types"
help
Use the full list of supported mime types.
Use this option if a "generic" webserver is used. However if it is
using only web pages (html, jpg, gif, png, css) then select this
option.
config CONFIG_HTTP_VERBOSE
bool "Verbose Mode"
default y if CONFIG_SSL_FULL_MODE
default n if !CONFIG_SSL_FULL_MODE
help
Enable extra statements used when using axhttpd.
config CONFIG_HTTP_IS_DAEMON
bool "Run as a daemon"
default n
depends on !CONFIG_PLATFORM_WIN32
help
Run axhttpd as a background process.
Does not work under Win32
endmenu

104
httpd/Makefile Normal file
View File

@ -0,0 +1,104 @@
#
# 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
#
all : web_server
include ../config/.config
include ../config/makefile.conf
ifndef CONFIG_PLATFORM_WIN32
ifdef CONFIG_PLATFORM_CYGWIN
TARGET=../$(STAGE)/axhttpd.exe
TARGET2=../$(STAGE)/htpasswd.exe
else
TARGET=../$(STAGE)/axhttpd
TARGET2=../$(STAGE)/htpasswd
endif
ifdef CONFIG_HTTP_STATIC_BUILD
LIBS=../$(STAGE)/libaxtls.a
else
LIBS=-L../$(STAGE) -laxtls
endif
CFLAGS += -I../ssl
else # win32 build
TARGET=../$(STAGE)/axhttpd.exe
TARGET2=../$(STAGE)/htpasswd.exe
ifdef CONFIG_HTTP_STATIC_BUILD
LIBS=../$(STAGE)/axtls.static.lib ..\\config\\axtls.res
else
LIBS=../$(STAGE)/axtls.lib ..\\config\\axtls.res
endif
endif
ifndef CONFIG_AXHTTPD
web_server:
else
web_server :: $(TARGET)
ifdef CONFIG_HTTP_HAS_AUTHORIZATION
web_server :: $(TARGET2)
endif
OBJ= \
axhttpd.o \
proc.o \
mime_types.o \
tdate_parse.o
include ../config/makefile.post
ifndef CONFIG_PLATFORM_WIN32
$(TARGET): $(OBJ) ../$(STAGE)/libaxtls.a
$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
ifndef CONFIG_DEBUG
ifndef CONFIG_PLATFORM_SOLARIS
strip --remove-section=.comment $(TARGET)
endif
endif
$(TARGET2): htpasswd.o ../$(STAGE)/libaxtls.a
$(LD) $(LDFLAGS) -o $@ htpasswd.o $(LIBS)
else # Win32
OBJ:=$(OBJ:.o=.obj)
%.obj : %.c
$(CC) $(CFLAGS) $<
htpasswd.obj : htpasswd.c
$(CC) $(CFLAGS) $<
$(TARGET): $(OBJ)
$(LD) $(LDFLAGS) $(LIBS) /out:$@ $(OBJ)
$(TARGET2): htpasswd.obj
$(LD) $(LDFLAGS) $(LIBS) /out:$@ $<
endif
endif # CONFIG_AXHTTPD
clean::
-@rm -f $(TARGET)*

133
httpd/axhttp.h Normal file
View File

@ -0,0 +1,133 @@
/*
* 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 "os_port.h"
#include "ssl.h"
#define BACKLOG 15
#define VERSION "1.0.0"
#ifdef CONFIG_HTTP_HAS_IPV6
#define HAVE_IPV6
#endif
#define MAXREQUESTLENGTH 256
#define MAXCGIARGS 100
#define BLOCKSIZE 4096
#define INITIAL_CONNECTION_SLOTS 10
#define CONFIG_HTTP_DEFAULT_SSL_OPTIONS 0
#define STATE_WANT_TO_READ_HEAD 1
#define STATE_WANT_TO_SEND_HEAD 2
#define STATE_WANT_TO_READ_FILE 3
#define STATE_WANT_TO_SEND_FILE 4
#define STATE_DOING_DIR 5
enum
{
TYPE_GET,
TYPE_HEAD,
TYPE_POST
};
struct connstruct
{
struct connstruct *next;
int state;
int reqtype;
int networkdesc;
int filedesc;
SSL *ssl;
#if defined(CONFIG_HTTP_DIRECTORIES)
#ifdef WIN32
HANDLE dirp;
WIN32_FIND_DATA file_data;
#else
DIR *dirp;
#endif
#endif
time_t timeout;
char actualfile[MAXREQUESTLENGTH];
char filereq[MAXREQUESTLENGTH];
char dirname[MAXREQUESTLENGTH];
char virtualhostreq[MAXREQUESTLENGTH];
int numbytes;
char databuf[BLOCKSIZE];
uint8_t is_ssl;
uint8_t close_when_done;
time_t if_modified_since;
#if defined(CONFIG_HTTP_HAS_CGI)
char cgiargs[MAXREQUESTLENGTH];
char cgiscriptinfo[MAXREQUESTLENGTH];
char cgipathinfo[MAXREQUESTLENGTH];
#endif
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
char authorization[MAXREQUESTLENGTH];
#endif
};
struct serverstruct
{
struct serverstruct *next;
int sd;
int is_ssl;
SSL_CTX *ssl_ctx;
};
#if defined(CONFIG_HTTP_HAS_CGI)
struct cgiextstruct
{
struct cgiextstruct *next;
char *ext;
};
#endif
/* global prototypes */
extern struct serverstruct *servers;
extern struct connstruct *usedconns;
extern struct connstruct *freeconns;
#if defined(CONFIG_HTTP_HAS_CGI)
extern struct cgiextstruct *cgiexts;
#endif
/* conn.c prototypes */
void removeconnection(struct connstruct *cn);
/* proc.c prototypes */
void procdodir(struct connstruct *cn);
void procreadhead(struct connstruct *cn);
void procsendhead(struct connstruct *cn);
void procreadfile(struct connstruct *cn);
void procsendfile(struct connstruct *cn);
/* misc.c prototypes */
char *my_strncpy(char *dest, const char *src, size_t n);
int isdir(const char *name);
/* mime_types.c prototypes */
void mime_init(void);
const char *getmimetype(const char *fn);
/* tdate prototypes */
void tdate_init(void);
time_t tdate_parse(const char* str);

567
httpd/axhttpd.c Normal file
View File

@ -0,0 +1,567 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "axhttp.h"
struct serverstruct *servers;
struct connstruct *usedconns;
struct connstruct *freeconns;
static void addtoservers(int sd);
static int openlistener(int port);
static void handlenewconnection(int listenfd, int is_ssl);
static void addconnection(int sd, char *ip, int is_ssl);
static void ax_chdir(void);
#if defined(CONFIG_HTTP_HAS_CGI)
struct cgiextstruct *cgiexts;
static void addcgiext(const char *tp);
#if !defined(WIN32)
static void reaper(int sigtype)
{
wait3(NULL, WNOHANG, NULL);
}
#endif
#endif
#ifdef CONFIG_HTTP_VERBOSE /* should really be in debug mode or something */
/* clean up memory for valgrind */
static void sigint_cleanup(int sig)
{
struct serverstruct *sp;
struct connstruct *tp;
while (servers != NULL)
{
if (servers->is_ssl)
ssl_ctx_free(servers->ssl_ctx);
sp = servers->next;
free(servers);
servers = sp;
}
while (freeconns != NULL)
{
tp = freeconns->next;
free(freeconns);
freeconns = tp;
}
while (usedconns != NULL)
{
tp = usedconns->next;
free(usedconns);
usedconns = tp;
}
#if defined(CONFIG_HTTP_HAS_CGI)
while (cgiexts)
{
struct cgiextstruct *cp = cgiexts->next;
if (cp == NULL) /* last entry */
free(cgiexts->ext);
free(cgiexts);
cgiexts = cp;
}
#endif
exit(0);
}
static void die(int sigtype)
{
exit(0);
}
#endif
int main(int argc, char *argv[])
{
fd_set rfds, wfds;
struct connstruct *tp, *to;
struct serverstruct *sp;
int rnum, wnum, active;
int i;
time_t currtime;
#ifdef WIN32
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData);
#else
signal(SIGPIPE, SIG_IGN);
#if defined(CONFIG_HTTP_HAS_CGI)
signal(SIGCHLD, reaper);
#endif
#ifdef CONFIG_HTTP_VERBOSE
signal(SIGQUIT, die);
#endif
#endif
#ifdef CONFIG_HTTP_VERBOSE
signal(SIGTERM, die);
signal(SIGINT, sigint_cleanup);
#endif
mime_init();
tdate_init();
for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++)
{
tp = freeconns;
freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct));
freeconns->next = tp;
}
if ((active = openlistener(CONFIG_HTTP_PORT)) == -1)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "ERR: Couldn't bind to port %d\n",
CONFIG_HTTP_PORT);
#endif
exit(1);
}
addtoservers(active);
if ((active = openlistener(CONFIG_HTTP_HTTPS_PORT)) == -1)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "ERR: Couldn't bind to port %d\n",
CONFIG_HTTP_HTTPS_PORT);
#endif
exit(1);
}
addtoservers(active);
servers->ssl_ctx = ssl_ctx_new(CONFIG_HTTP_DEFAULT_SSL_OPTIONS,
CONFIG_HTTP_SESSION_CACHE_SIZE);
servers->is_ssl = 1;
#if defined(CONFIG_HTTP_HAS_CGI)
addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
#endif
#if defined(CONFIG_HTTP_VERBOSE)
printf("axhttpd (%s): listening on ports %d (http) and %d (https)\n",
ssl_version(), CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT);
TTY_FLUSH();
#endif
ax_chdir();
#ifndef WIN32
#ifdef CONFIG_HTTP_CHANGE_UID
setgid(32767);
setuid(32767);
#endif
#ifdef CONFIG_HTTP_IS_DAEMON
if (fork() > 0) /* parent will die */
exit(0);
setsid();
#endif
#endif
/* main loop */
while (1)
{
FD_ZERO(&rfds);
FD_ZERO(&wfds);
rnum = wnum = -1;
sp = servers;
while (sp != NULL) /* read each server port */
{
FD_SET(sp->sd, &rfds);
if (sp->sd > rnum)
rnum = sp->sd;
sp = sp->next;
}
/* Add the established sockets */
tp = usedconns;
currtime = time(NULL);
while (tp != NULL)
{
if (currtime > tp->timeout) /* timed out? Kill it. */
{
to = tp;
tp = tp->next;
removeconnection(to);
continue;
}
if (tp->state == STATE_WANT_TO_READ_HEAD)
{
FD_SET(tp->networkdesc, &rfds);
if (tp->networkdesc > rnum)
rnum = tp->networkdesc;
}
if (tp->state == STATE_WANT_TO_SEND_HEAD)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
if (tp->state == STATE_WANT_TO_READ_FILE)
{
FD_SET(tp->filedesc, &rfds);
if (tp->filedesc > rnum)
rnum = tp->filedesc;
}
if (tp->state == STATE_WANT_TO_SEND_FILE)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
#if defined(CONFIG_HTTP_DIRECTORIES)
if (tp->state == STATE_DOING_DIR)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
#endif
tp = tp->next;
}
active = select(wnum > rnum ? wnum+1 : rnum+1,
rnum != -1 ? &rfds : NULL,
wnum != -1 ? &wfds : NULL,
NULL, NULL);
/* New connection? */
sp = servers;
while (active > 0 && sp != NULL)
{
if (FD_ISSET(sp->sd, &rfds))
{
handlenewconnection(sp->sd, sp->is_ssl);
active--;
}
sp = sp->next;
}
/* Handle the established sockets */
tp = usedconns;
while (active > 0 && tp != NULL)
{
to = tp;
tp = tp->next;
if (to->state == STATE_WANT_TO_READ_HEAD &&
FD_ISSET(to->networkdesc, &rfds))
{
active--;
procreadhead(to);
}
if (to->state == STATE_WANT_TO_SEND_HEAD &&
FD_ISSET(to->networkdesc, &wfds))
{
active--;
procsendhead(to);
}
if (to->state == STATE_WANT_TO_READ_FILE &&
FD_ISSET(to->filedesc, &rfds))
{
active--;
procreadfile(to);
}
if (to->state == STATE_WANT_TO_SEND_FILE &&
FD_ISSET(to->networkdesc, &wfds))
{
active--;
procsendfile(to);
}
#if defined(CONFIG_HTTP_DIRECTORIES)
if (to->state == STATE_DOING_DIR &&
FD_ISSET(to->networkdesc, &wfds))
{
active--;
procdodir(to);
}
#endif
}
}
return 0;
}
#if defined(CONFIG_HTTP_HAS_CGI)
static void addcgiext(const char *cgi_exts)
{
char *cp = strdup(cgi_exts);
/* extenstions are comma separated */
do
{
struct cgiextstruct *ex = (struct cgiextstruct *)
malloc(sizeof(struct cgiextstruct));
ex->ext = cp;
ex->next = cgiexts;
cgiexts = ex;
if ((cp = strchr(cp, ',')) != NULL)
*cp++ = 0;
} while (cp != NULL);
}
#endif
static void addtoservers(int sd)
{
struct serverstruct *tp = (struct serverstruct *)
calloc(1, sizeof(struct serverstruct));
tp->next = servers;
tp->sd = sd;
servers = tp;
}
#ifdef HAVE_IPV6
static void handlenewconnection(int listenfd, int is_ssl)
{
struct sockaddr_in6 their_addr;
int tp = sizeof(their_addr);
char ipbuf[100];
int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
if (tp == sizeof(struct sockaddr_in6))
inet_ntop(AF_INET6, &their_addr.sin6_addr, ipbuf, sizeof(ipbuf));
else if (tp == sizeof(struct sockaddr_in))
inet_ntop(AF_INET, &(((struct sockaddr_in *)&their_addr)->sin_addr),
ipbuf, sizeof(ipbuf));
else
*ipbuf = '\0';
addconnection(connfd, ipbuf, is_ssl);
}
#else
static void handlenewconnection(int listenfd, int is_ssl)
{
struct sockaddr_in their_addr;
socklen_t tp = sizeof(struct sockaddr_in);
int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
addconnection(connfd, inet_ntoa(their_addr.sin_addr), is_ssl);
}
#endif
static int openlistener(int port)
{
int sd;
#ifdef WIN32
char tp = 1;
#else
int tp = 1;
#endif
#ifndef HAVE_IPV6
struct sockaddr_in my_addr;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return -1;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons((short)port);
my_addr.sin_addr.s_addr = INADDR_ANY;
#else
struct sockaddr_in6 my_addr;
if ((sd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
return -1;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin6_family = AF_INET6;
my_addr.sin6_port = htons(port);
my_addr.sin6_addr.s_addr = INADDR_ANY;
#endif
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp));
if (bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
close(sd);
return -1;
}
listen(sd, BACKLOG);
return sd;
}
/* Wrapper function for strncpy() that guarantees
a null-terminated string. This is to avoid any possible
issues due to strncpy()'s behaviour.
*/
char *my_strncpy(char *dest, const char *src, size_t n)
{
strncpy(dest, src, n);
dest[n-1] = '\0';
return dest;
}
int isdir(const char *tpbuf)
{
struct stat st;
char path[MAXREQUESTLENGTH];
strcpy(path, tpbuf);
#ifdef WIN32 /* win32 stat() can't handle trailing '\' */
if (path[strlen(path)-1] == '\\')
path[strlen(path)-1] = 0;
#endif
if (stat(path, &st) == -1)
return 0;
if ((st.st_mode & S_IFMT) == S_IFDIR)
return 1;
return 0;
}
static void addconnection(int sd, char *ip, int is_ssl)
{
struct connstruct *tp;
/* Get ourselves a connstruct */
if (freeconns == NULL)
tp = (struct connstruct *)calloc(1, sizeof(struct connstruct));
else
{
tp = freeconns;
freeconns = tp->next;
}
/* Attach it to the used list */
tp->next = usedconns;
usedconns = tp;
tp->networkdesc = sd;
if (is_ssl)
tp->ssl = ssl_server_new(servers->ssl_ctx, sd);
tp->is_ssl = is_ssl;
tp->filedesc = -1;
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
tp->dirp = NULL;
#endif
*(tp->actualfile) = '\0';
*(tp->filereq) = '\0';
#if defined(CONFIG_HTTP_HAS_CGI)
*(tp->cgiargs) = '\0';
#endif
tp->state = STATE_WANT_TO_READ_HEAD;
tp->reqtype = TYPE_GET;
tp->close_when_done = 0;
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
}
void removeconnection(struct connstruct *cn)
{
struct connstruct *tp;
int shouldret = 0;
tp = usedconns;
if (tp == NULL || cn == NULL)
shouldret = 1;
else if (tp == cn)
usedconns = tp->next;
else
{
while (tp != NULL)
{
if (tp->next == cn)
{
tp->next = (tp->next)->next;
shouldret = 0;
break;
}
tp = tp->next;
shouldret = 1;
}
}
if (shouldret)
return;
/* If we did, add it to the free list */
cn->next = freeconns;
freeconns = cn;
/* Close it all down */
if (cn->networkdesc != -1)
{
if (cn->is_ssl)
{
ssl_free(cn->ssl);
cn->ssl = NULL;
}
SOCKET_CLOSE(cn->networkdesc);
}
if (cn->filedesc != -1)
close(cn->filedesc);
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
if (cn->dirp != NULL)
#ifdef WIN32
FindClose(cn->dirp);
#else
closedir(cn->dirp);
#endif
#endif
}
/*
* Change directories one way or the other.
*/
static void ax_chdir(void)
{
static char *webroot = CONFIG_HTTP_WEBROOT;
#if defined(WIN32) || !defined(CONFIG_HTTP_USE_CHROOT)
if (chdir(webroot))
#else /* use chroot() instead */
if (chroot(webroot))
#endif
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "'%s' is not a directory\n", webroot);
#endif
exit(1);
}
}

124
httpd/htpasswd.c Normal file
View File

@ -0,0 +1,124 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ssl.h"
int tfd;
void base64_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen)
{
static const char b64str[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (inlen && outlen)
{
*out++ = b64str[(in[0] >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64str[((in[0] << 4)
+ (--inlen ? in[1] >> 4 : 0)) & 0x3f];
if (!--outlen)
break;
*out++ = (inlen
? b64str[((in[1] << 2)
+ (--inlen ? in[2] >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64str[in[2] & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
if (outlen)
*out = '\0';
}
static void usage(void)
{
fprintf(stderr,"Usage: htpasswd username\n");
exit(1);
}
#ifdef WIN32
static char * getpass(const char *prompt)
{
static char buf[127];
FILE *fp = stdin;
printf(prompt); TTY_FLUSH();
#if 0
fp = fopen("/dev/tty", "w");
if (fp == NULL)
{
printf("null\n"); TTY_FLUSH();
fp = stdin;
}
#endif
fgets(buf, sizeof(buf), fp);
while (buf[strlen(buf)-1] < ' ')
buf[strlen(buf)-1] = '\0';
//if (fp != stdin)
// fclose(fp);
return buf;
}
#endif
int main(int argc, char *argv[])
{
char* pw;
uint8_t md5_salt[MD5_SIZE], md5_pass[MD5_SIZE];
char b64_salt[MD5_SIZE+10], b64_pass[MD5_SIZE+10];
MD5_CTX ctx;
if (argc != 2)
usage();
pw = strdup(getpass("New password:"));
if (strcmp(pw, getpass("Re-type new password:")) != 0)
{
fprintf(stderr, "They don't match, sorry.\n" );
exit(1);
}
RNG_initialize((uint8_t *)pw, sizeof(pw));
get_random(MD5_SIZE, md5_salt);
RNG_terminate();
base64_encode(md5_salt, MD5_SIZE, b64_salt, sizeof(b64_salt));
MD5Init(&ctx);
MD5Update(&ctx, md5_salt, MD5_SIZE);
MD5Update(&ctx, (uint8_t *)pw, strlen(pw));
MD5Final(&ctx, md5_pass);
base64_encode(md5_pass, MD5_SIZE, b64_pass, sizeof(b64_pass));
printf("Add the following to your '.htpasswd' file\n");
printf("%s:%s$%s\n", argv[1], b64_salt, b64_pass);
return 0;
}

194
httpd/mime_types.c Normal file
View File

@ -0,0 +1,194 @@
/*
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "axhttp.h"
static const char mime_default[] = "text/plain";
typedef struct
{
const char * const ext;
const char * const type;
} mime_table_t;
static mime_table_t mime_table[] =
{
/* Fundamental types */
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".css", "text/css" },
/* Basic graphics */
{ ".jpg", "image/jpeg" },
{ ".gif", "image/gif" },
{ ".png", "image/png" },
#ifdef CONFIG_HTTP_ALL_MIME_TYPES
/* This list is a bit expensive to maintain normally, so it's an option. */
{ ".txt", "text/plain" },
{ ".rtx", "text/richtext" },
{ ".etx", "text/x-setext" },
{ ".tsv", "text/tab-separated-values" },
{ ".xml", "text/xml" },
{ ".dtd", "text/xml" },
{ ".jpe", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
{ ".jfif", "image/jpeg" },
{ ".tif", "image/tiff" },
{ ".tiff", "image/tiff" },
{ ".pbm", "image/x-portable-bitmap" },
{ ".pgm", "image/x-portable-graymap" },
{ ".ppm", "image/x-portable-pixmap" },
{ ".pnm", "image/x-portable-anymap" },
{ ".xbm", "image/x-xbitmap" },
{ ".xpm", "image/x-xpixmap" },
{ ".xwd", "image/x-xwindowdump" },
{ ".ief", "image/ief" },
{ ".au", "audio/basic" },
{ ".snd", "audio/basic" },
{ ".aif", "audio/x-aiff" },
{ ".aiff", "audio/x-aiff" },
{ ".aifc", "audio/x-aiff" },
{ ".ra", "audio/x-pn-realaudio" },
{ ".ram", "audio/x-pn-realaudio" },
{ ".rm", "audio/x-pn-realaudio" },
{ ".rpm", "audio/x-pn-realaudio-plugin" },
{ ".wav", "audio/wav" },
{ ".mid", "audio/midi" },
{ ".midi", "audio/midi" },
{ ".kar", "audio/midi" },
{ ".mpga", "audio/mpeg" },
{ ".mp2", "audio/mpeg" },
{ ".mp3", "audio/mpeg" },
{ ".mpeg", "video/mpeg" },
{ ".mpg", "video/mpeg" },
{ ".mpe", "video/mpeg" },
{ ".qt", "video/quicktime" },
{ ".mov", "video/quicktime" },
{ ".avi", "video/x-msvideo" },
{ ".movie", "video/x-sgi-movie" },
{ ".mv", "video/x-sgi-movie" },
{ ".vx", "video/x-rad-screenplay" },
{ ".a", "application/octet-stream" },
{ ".bin", "application/octet-stream" },
{ ".exe", "application/octet-stream" },
{ ".dump", "application/octet-stream" },
{ ".o", "application/octet-stream" },
{ ".class", "application/java" },
{ ".js", "application/x-javascript" },
{ ".ai", "application/postscript" },
{ ".eps", "application/postscript" },
{ ".ps", "application/postscript" },
{ ".dir", "application/x-director" },
{ ".dcr", "application/x-director" },
{ ".dxr", "application/x-director" },
{ ".fgd", "application/x-director" },
{ ".aam", "application/x-authorware-map" },
{ ".aas", "application/x-authorware-seg" },
{ ".aab", "application/x-authorware-bin" },
{ ".fh4", "image/x-freehand" },
{ ".fh7", "image/x-freehand" },
{ ".fh5", "image/x-freehand" },
{ ".fhc", "image/x-freehand" },
{ ".fh", "image/x-freehand" },
{ ".spl", "application/futuresplash" },
{ ".swf", "application/x-shockwave-flash" },
{ ".dvi", "application/x-dvi" },
{ ".gtar", "application/x-gtar" },
{ ".hdf", "application/x-hdf" },
{ ".hqx", "application/mac-binhex40" },
{ ".iv", "application/x-inventor" },
{ ".latex", "application/x-latex" },
{ ".man", "application/x-troff-man" },
{ ".me", "application/x-troff-me" },
{ ".mif", "application/x-mif" },
{ ".ms", "application/x-troff-ms" },
{ ".oda", "application/oda" },
{ ".pdf", "application/pdf" },
{ ".rtf", "application/rtf" },
{ ".bcpio", "application/x-bcpio" },
{ ".cpio", "application/x-cpio" },
{ ".sv4cpio", "application/x-sv4cpio" },
{ ".sv4crc", "application/x-sv4crc" },
{ ".sh", "application/x-shar" },
{ ".shar", "application/x-shar" },
{ ".sit", "application/x-stuffit" },
{ ".tar", "application/x-tar" },
{ ".tex", "application/x-tex" },
{ ".texi", "application/x-texinfo" },
{ ".texinfo", "application/x-texinfo" },
{ ".tr", "application/x-troff" },
{ ".roff", "application/x-troff" },
{ ".man", "application/x-troff-man" },
{ ".me", "application/x-troff-me" },
{ ".ms", "application/x-troff-ms" },
{ ".zip", "application/x-zip-compressed" },
{ ".tsp", "application/dsptype" },
{ ".wsrc", "application/x-wais-source" },
{ ".ustar", "application/x-ustar" },
{ ".cdf", "application/x-netcdf" },
{ ".nc", "application/x-netcdf" },
{ ".doc", "application/msword" },
{ ".ppt", "application/powerpoint" },
{ ".wrl", "model/vrml" },
{ ".vrml", "model/vrml" },
{ ".mime", "message/rfc822" },
{ ".pac", "application/x-ns-proxy-autoconfig" },
{ ".wml", "text/vnd.wap.wml" },
{ ".wmlc", "application/vnd.wap.wmlc" },
{ ".wmls", "text/vnd.wap.wmlscript" },
{ ".wmlsc", "application/vnd.wap.wmlscriptc" },
{ ".wbmp", "image/vnd.wap.wbmp" },
{ ".tgz", "application/x-gzip" },
{ ".tar.gz", "application/x-gzip" },
{ ".bz2", "application/x-bzip2" },
{ ".zip", "application/zip" }
#endif
};
static int mime_cmp(const mime_table_t *t1, const mime_table_t *t2)
{
return strcasecmp(t1->ext, t2->ext);
}
void mime_init(void)
{
qsort(mime_table, sizeof(mime_table)/sizeof(mime_table_t),
sizeof(mime_table_t),
(int (*)(const void *, const void *))mime_cmp);
}
const char *getmimetype(const char *name)
{
mime_table_t *mime_type;
if ((name = strrchr(name, '.')) == NULL)
return mime_default;
mime_type = bsearch(&name, mime_table,
sizeof(mime_table)/sizeof(mime_table_t),
sizeof(mime_table_t),
(int (*)(const void *, const void *))mime_cmp);
return mime_type == NULL ? mime_default : mime_type->type;
}

1034
httpd/proc.c Normal file

File diff suppressed because it is too large Load Diff

107
httpd/tdate_parse.c Normal file
View File

@ -0,0 +1,107 @@
/*
* 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 <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "axhttp.h"
struct day_mon_map
{
const char* s;
uint8_t l;
};
static struct day_mon_map wday_tab[] =
{
{ "Sun", 0 }, { "Mon", 1 }, { "Tue", 2 }, { "Wed", 3 },
{ "Thu", 4 }, { "Fri", 5 }, { "Sat", 6 },
};
static struct day_mon_map mon_tab[] =
{
{ "Jan", 0 }, { "Feb", 1 }, { "Mar", 2 }, { "Apr", 3 },
{ "May", 4 }, { "Jun", 5 }, { "Jul", 6 }, { "Aug", 7 },
{ "Sep", 8 }, { "Oct", 9 }, { "Nov", 10 }, { "Dec", 11 },
};
static int day_mon_map_compare(const char *v1, const char *v2)
{
return strcmp(((struct day_mon_map*)v1)->s, ((struct day_mon_map*)v2)->s);
}
void tdate_init(void)
{
qsort(wday_tab, sizeof(wday_tab)/sizeof(struct day_mon_map),
sizeof(struct day_mon_map),
(int (*)(const void *, const void *))day_mon_map_compare);
qsort(mon_tab, sizeof(mon_tab)/sizeof(struct day_mon_map),
sizeof(struct day_mon_map),
(int (*)(const void *, const void *))day_mon_map_compare);
}
static int8_t day_mon_map_search(const char* str,
const struct day_mon_map* tab, int n)
{
struct day_mon_map *search = bsearch(&str, tab, n,
sizeof(struct day_mon_map),
(int (*)(const void *, const void *))day_mon_map_compare);
return search ? search->l : -1;
}
time_t tdate_parse(const char* str)
{
struct tm tm;
char str_mon[4], str_wday[4];
int tm_sec, tm_min, tm_hour, tm_mday, tm_year;
/* Initialize. */
memset(&tm, 0, sizeof(struct tm));
/* wdy, DD mth YY HH:MM:SS GMT */
if ((sscanf(str, "%3[a-zA-Z], %d %3[a-zA-Z] %d %d:%d:%d GMT",
str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
&tm_sec) == 7) ||
/* wdy mth DD HH:MM:SS YY */
(sscanf(str, "%3[a-zA-Z] %3[a-zA-Z] %d %d:%d:%d %d",
str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
&tm_year) == 7))
{
int8_t tm_wday = day_mon_map_search(str_wday, wday_tab,
sizeof(wday_tab)/sizeof(struct day_mon_map));
int8_t tm_mon = day_mon_map_search(str_mon, mon_tab,
sizeof(mon_tab)/sizeof(struct day_mon_map));
if (tm_wday < 0 || tm_mon < 0)
return -1;
tm.tm_wday = tm_wday;
tm.tm_mon = tm_mon;
tm.tm_mday = tm_mday;
tm.tm_hour = tm_hour;
tm.tm_min = tm_min;
tm.tm_sec = tm_sec;
tm.tm_year = tm_year - 1900;
return mktime(&tm);
}
return -1; /* error */
}

56
samples/Config.in Normal file
View File

@ -0,0 +1,56 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "Samples"
config CONFIG_SAMPLES
bool "Create Samples"
default y
help
axTLS contains various sample code.
Select Y here if you want to build the various samples.
config CONFIG_C_SAMPLES
bool "axssl - C version"
default y
depends on CONFIG_SAMPLES
help
Build the "C" version of axssl. The features enabled are very
dependent on the build mode ('full' mode will give all features).
config CONFIG_CSHARP_SAMPLES
bool "axssl - C# version"
default y
depends on CONFIG_SAMPLES && CONFIG_CSHARP_BINDINGS
help
Build the "C#" version of axssl. The features enabled are very
dependent on the build mode ('full' mode will give all features).
config CONFIG_VBNET_SAMPLES
bool "axssl - VB.NET version"
default y
depends on CONFIG_SAMPLES && CONFIG_VBNET_BINDINGS
help
Build the "VB.NET" version of axssl. The features enabled are very
dependent on the build mode ('full' mode will give all features).
config CONFIG_JAVA_SAMPLES
bool "axssl - Java version"
default y
depends on CONFIG_SAMPLES && CONFIG_JAVA_BINDINGS
help
Build the "Java" version of axssl. The features enabled are very
dependent on the build mode ('full' mode will give all features).
config CONFIG_PERL_SAMPLES
bool "axssl - Perl version"
default y
depends on CONFIG_SAMPLES && CONFIG_PERL_BINDINGS
help
Build the "Perl" version of axssl. The features enabled are very
dependent on the build mode ('full' mode will give all features).
endmenu

46
samples/Makefile Normal file
View File

@ -0,0 +1,46 @@
#
# 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 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
#
all:
include ../config/.config
include ../config/makefile.conf
all:
ifdef CONFIG_C_SAMPLES
$(MAKE) -C c
endif
ifdef CONFIG_CSHARP_SAMPLES
$(MAKE) -C csharp
endif
ifdef CONFIG_VBNET_SAMPLES
$(MAKE) -C vbnet
endif
ifdef CONFIG_JAVA_SAMPLES
$(MAKE) -C java
endif
ifdef CONFIG_PERL_SAMPLES
$(MAKE) -C perl
endif
clean::
$(MAKE) -C c clean
$(MAKE) -C csharp clean
$(MAKE) -C vbnet clean
$(MAKE) -C java clean
$(MAKE) -C perl clean

66
samples/c/Makefile Normal file
View File

@ -0,0 +1,66 @@
#
# 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 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
#
all : sample
include ../../config/.config
include ../../config/makefile.conf
ifndef CONFIG_PLATFORM_WIN32
ifdef CONFIG_PLATFORM_CYGWIN
TARGET=../../$(STAGE)/axssl.exe
else
TARGET=../../$(STAGE)/axssl
endif # cygwin
LIBS=../../$(STAGE)
CFLAGS += -I../../ssl -I../../config
else
TARGET=../../$(STAGE)/axssl.exe
CFLAGS += /I"..\..\ssl" /I"..\..\config"
endif
ifndef CONFIG_C_SAMPLES
sample:
else
sample : $(TARGET)
OBJ= axssl.o
include ../../config/makefile.post
ifndef CONFIG_PLATFORM_WIN32
$(TARGET): $(OBJ) $(LIBS)/libaxtls.a
$(LD) $(LDFLAGS) -o $@ $< -L$(LIBS) -laxtls
ifndef CONFIG_DEBUG
ifndef CONFIG_PLATFORM_SOLARIS
strip --remove-section=.comment $(TARGET)
endif # SOLARIS
endif # CONFIG_DEBUG
else # Win32
$(TARGET): $(OBJ)
$(LD) $(LDFLAGS) ..\\..\\config\\axtls.res /out:$@ $^ /libpath:"../../$(STAGE)" axtls.lib
endif
endif # CONFIG_C_SAMPLES
clean::
-@rm -f ../../$(STAGE)/axssl*

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

@ -0,0 +1,865 @@
/*
* 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 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 "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\n", ssl_version());
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++;
}
/* 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.
*************************************************************************/
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
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)
{
res = 1;
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 > 0) /* display our interesting output */
{
printf("%s", read_buf);
TTY_FLUSH();
}
else if (res < 0 && !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;
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];
}
#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++;
}
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();
}
/*************************************************************************
* This is where the interesting stuff happens. Up until now we've
* just been setting up sockets etc. Now we do the SSL handshake.
*************************************************************************/
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);
/* Try session resumption? */
if (reconnect)
{
while (reconnect--)
{
ssl = ssl_client_new(ssl_ctx, client_fd, session_id);
if ((res = ssl_handshake_status(ssl)) != SSL_OK)
{
if (!quiet)
{
ssl_display_error(res);
}
ssl_free(ssl);
exit(1);
}
display_session_id(ssl);
memcpy(session_id, ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);
if (reconnect)
{
ssl_free(ssl);
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);
}
/* 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%s\n", common_name);
}
display_session_id(ssl);
display_cipher(ssl);
}
for (;;)
{
uint8_t buf[1024];
res = SSL_OK;
/* 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)+1);
}
}
}
#ifndef WIN32
else /* a socket read */
{
uint8_t *read_buf;
res = ssl_read(ssl, &read_buf);
if (res > 0) /* display our interesting output */
{
printf("%s", read_buf);
TTY_FLUSH();
}
}
}
#endif
if (res < 0)
{
if (!quiet)
{
ssl_display_error(res);
}
break; /* get outta here */
}
}
ssl_ctx_free(ssl_ctx);
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");
#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_RC4_128_SHA:
printf("RC4-SHA");
break;
case SSL_RC4_128_MD5:
printf("RC4-MD5");
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);
printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
for (i = 0; i < SSL_SESSION_ID_SIZE; i++)
{
printf("%02x", session_id[i]);
}
printf("\n-----END SSL SESSION PARAMETERS-----\n");
TTY_FLUSH();
}

36
samples/csharp/Makefile Normal file
View File

@ -0,0 +1,36 @@
#
# 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 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
include ../../config/makefile.dotnet.conf
all : sample
TARGET=../../$(STAGE)/axssl.csharp.exe
sample : $(TARGET)
$(TARGET): ../../bindings/csharp/axTLS.cs ../../bindings/csharp/axInterface.cs axssl.cs
ifdef GO_DOT_NET
csc.exe /nologo /t:exe /out:"`cygpath -w $@`" $(foreach file, $^, "`cygpath -w $(file)`")
else # use mono to build
mcs -out:$@ $^
endif # ARCH
clean::
-@rm -f $(TARGET)

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

@ -0,0 +1,743 @@
/*
* 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 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" + 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_RC4_128_SHA:
Console.WriteLine("RC4-SHA");
break;
case axtls.SSL_RC4_128_MD5:
Console.WriteLine("RC4-MD5");
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();
Console.WriteLine("-----BEGIN SSL SESSION PARAMETERS-----");
foreach (byte b in session_id)
{
Console.Write("{0:x02}", b);
}
Console.WriteLine("\n-----END SSL SESSION PARAMETERS-----");
}
}

39
samples/java/Makefile Normal file
View File

@ -0,0 +1,39 @@
#
# 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 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
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)

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

@ -0,0 +1,746 @@
/*
* 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 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" + 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_RC4_128_SHA)
System.out.println("RC4-SHA");
else if (ciph_id == axtlsj.SSL_RC4_128_MD5)
System.out.println("RC4-MD5");
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();
int i;
System.out.println("-----BEGIN SSL SESSION PARAMETERS-----");
bytesToHex(session_id);
System.out.println("-----END SSL SESSION PARAMETERS-----");
}
}

1
samples/java/manifest.mf Normal file
View File

@ -0,0 +1 @@
Main-Class: axssl

31
samples/perl/Makefile Normal file
View File

@ -0,0 +1,31 @@
#
# 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 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.pl
samples: $(TARGET)
$(TARGET): axssl.pl
install $< $@
clean::
-@rm -f $(TARGET)

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

@ -0,0 +1,629 @@
#!/usr/bin/perl -w
#
# 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 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;
}
#
# Main entry point. Doesn't do much except works out whether we are a client
# or a server.
#
if ($#ARGV == 0 && $ARGV[0] eq "version")
{
printf("axssl.pl ".axtlsp::ssl_version()."\n");
exit 0;
}
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;
while (1)
{
($res, $buf) = axtlsp::ssl_read($ssl, undef);
last if $res != $axtlsp::SSL_OK;
# check when the connection has been established
last if axtlsp::ssl_handshake_status($ssl) == $axtlsp::SSL_OK;
# could do something else here
}
if ($res == $axtlsp::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 (1)
{
($res, $buf) = axtlsp::ssl_read($ssl, undef);
last if $res != $axtlsp::SSL_OK;
# could do something else here
}
if ($res < $axtlsp::SSL_OK)
{
printf("CONNECTION CLOSED\n") if not $quiet;
last;
}
printf($$buf);
}
}
elsif (!$quiet)
{
axtlsp::ssl_display_error($res);
}
# client was disconnected or the handshake failed.
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;
while ($reconnect--)
{
$ssl = axtlsp::ssl_client_new($ssl_ctx, $native_sock, $session_id);
$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);
}
# 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%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] [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 default DER format. 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_RC4_128_SHA)
{
printf("RC4-SHA");
}
elsif ($axtlsp::SSL_RC4_128_MD5)
{
printf("RC4-MD5");
}
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);
printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
printf(unpack("H*", $$session_id));
printf("\n-----END SSL SESSION PARAMETERS-----\n");
}

36
samples/vbnet/Makefile Normal file
View File

@ -0,0 +1,36 @@
#
# 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 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
include ../../config/makefile.dotnet.conf
# only build on Win32 platforms
ifdef GO_DOT_NET
all : sample
TARGET=../../$(STAGE)/axssl.vbnet.exe
sample : $(TARGET)
$(TARGET): ../../bindings/vbnet/axTLSvb.vb ../../bindings/vbnet/axInterface.vb axssl.vb
vbc.exe /r:"`cygpath -w "$(CONFIG_DOT_NET_FRAMEWORK_BASE)/System.dll"`" /nologo /t:exe /out:"`cygpath -w $@`" $(foreach file, $^, "`cygpath -w $(file)`")
endif # ARCH
clean::
-@rm -f $(TARGET)

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

@ -0,0 +1,687 @@
'
' 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 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 & 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_RC4_128_SHA
Console.WriteLine("RC4-SHA")
Case axtls.SSL_RC4_128_MD5
Console.WriteLine("RC4-MD5")
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()
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 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

132
ssl/BigIntConfig.in Normal file
View File

@ -0,0 +1,132 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "BigInt Options"
depends on !CONFIG_SSL_SKELETON_MODE
choice
prompt "Reduction Algorithm"
default CONFIG_BIGINT_BARRETT
config CONFIG_BIGINT_CLASSICAL
bool "Classical"
help
Classical uses standard division. It has no limitations and is
theoretically the slowest due to the divisions used. For this particular
implementation it is surprisingly quite fast.
config CONFIG_BIGINT_MONTGOMERY
bool "Montgomery"
help
Montgomery uses simple addition and multiplication to achieve its
performance. In this implementation it is slower than classical,
and it has the limitation that 0 <= x, y < m, and so is not used
when CRT is active.
This option will not be normally selected.
config CONFIG_BIGINT_BARRETT
bool "Barrett"
help
Barrett performs expensive precomputation before reduction and partial
multiplies for computational speed. It can't be used with some of the
calculations when CRT is used, and so defaults to classical when this
occurs.
It is about 40% faster than Classical/Montgomery with the expense of
about 2kB, and so this option is normally selected.
endchoice
config CONFIG_BIGINT_CRT
bool "Chinese Remainder Theorem (CRT)"
default y
help
Allow the Chinese Remainder Theorem (CRT) to be used.
Uses a number of extra coefficients from the private key to improve the
performance of a decryption. This feature is one of the most
significant performance improvements (it reduces a decryption time by
over 3 times).
This option should be selected.
config CONFIG_BIGINT_KARATSUBA
bool "Karatsuba Multiplication"
default n
help
Allow Karasuba multiplication to be used.
Uses 3 multiplications (plus a number of additions/subtractions)
instead of 4. Multiplications are O(N^2) but addition/subtraction
is O(N) hence for large numbers is beneficial. For this project, the
effect was only useful for 4096 bit keys. As these aren't likely to
be used, the feature is disabled by default.
It costs about 2kB to enable it.
config MUL_KARATSUBA_THRESH
int "Karatsuba Multiplication Theshold"
default 20
depends on CONFIG_BIGINT_KARATSUBA
help
The minimum number of components needed before Karasuba muliplication
is used.
This is very dependent on the speed/implementation of bi_add()/
bi_subtract(). There is a bit of trial and error here and will be
at a different point for different architectures.
config SQU_KARATSUBA_THRESH
int "Karatsuba Square Threshold"
default 40
depends on CONFIG_BIGINT_KARATSUBA && CONFIG_BIGINT_SQUARE
help
The minimum number of components needed before Karatsuba squaring
is used.
This is very dependent on the speed/implementation of bi_add()/
bi_subtract(). There is a bit of trial and error here and will be
at a different point for different architectures.
config CONFIG_BIGINT_SLIDING_WINDOW
bool "Sliding Window Exponentiation"
default y
help
Allow Sliding-Window Exponentiation to be used.
Potentially processes more than 1 bit at a time when doing
exponentiation. The sliding-window technique reduces the number of
precomputations compared to other precomputed techniques.
It results in a considerable performance improvement with it enabled
(it halves the decryption time) and so should be selected.
config CONFIG_BIGINT_SQUARE
bool "Square Algorithm"
default y
help
Allow squaring to be used instead of a multiplication.
Squaring is theoretically 50% faster than a standard multiply
(but is actually about 25% faster).
It gives a 20% speed improvement and so should be selected.
config CONFIG_BIGINT_CHECK_ON
bool "BigInt Integrity Checking"
default n if !CONFIG_DEBUG
default y if CONFIG_DEBUG
help
This is used when developing bigint algorithms. It performs a sanity
check on all operations at the expense of speed.
This option is only selected when developing and should normally be
turned off.
endmenu

274
ssl/Config.in Normal file
View File

@ -0,0 +1,274 @@
#
# For a description of the syntax of this configuration file,
# see scripts/config/Kconfig-language.txt
#
menu "SSL Library"
choice
prompt "Mode"
default CONFIG_SSL_FULL_MODE
config CONFIG_SSL_SERVER_ONLY
bool "Server only - no verification"
help
Enable server functionality (no client functionality).
This mode still supports sessions and chaining (which can be turned
off in configuration).
The axssl sample runs with the minimum of features.
This is the most space efficient of the modes with the library
about 45kB in size. Use this mode if you are doing standard SSL server
work.
config CONFIG_SSL_CERT_VERIFICATION
bool "Server only - with verification"
help
Enable server functionality with client authentication (no client
functionality).
The axssl sample runs with the "-verify" and "-CAfile" options.
This mode produces a library about 49kB in size. Use this mode if you
have an SSL server which requires client authentication (which is
uncommon in browser applications).
config CONFIG_SSL_ENABLE_CLIENT
bool "Client/Server enabled"
help
Enable client/server functionality (including peer authentication).
The axssl sample runs with the "s_client" option enabled.
This mode produces a library about 51kB in size. Use this mode if you
require axTLS to use SSL client functionality (the SSL server code
is always enabled).
config CONFIG_SSL_FULL_MODE
bool "Client/Server enabled with diagnostics"
help
Enable client/server functionality including diagnostics. Most of the
extra size in this mode is due to the storage of various strings that
are used.
The axssl sample has 3 more options, "-debug", "-state" and "-show-rsa"
This mode produces a library about 58kB in size. It is suggested that
this mode is used only during development, or systems that have more
generous memory limits.
It is the default to demonstrate the features of axTLS.
config CONFIG_SSL_SKELETON_MODE
bool "Skeleton mode - the smallest server mode"
help
This is an experiment to build the smallest library at the expense of
features and speed.
* Server mode only.
* The AES cipher is disabled.
* No session resumption.
* No external keys/certificates are supported.
* The bigint library has most of the performance features disabled.
* Some other features/API calls may not work.
This mode produces a library about 37kB in size. The main
disadvantage of this mode is speed - it will be much slower than the
other build modes.
endchoice
choice
prompt "Protocol Preference"
depends on !CONFIG_SSL_SKELETON_MODE
default CONFIG_SSL_PROT_MEDIUM
config CONFIG_SSL_PROT_LOW
bool "Low"
help
Chooses the cipher in the order of RC4-SHA, AES128-SHA, AES256-SHA.
This will use the fastest cipher(s) but at the expense of security.
config CONFIG_SSL_PROT_MEDIUM
bool "Medium"
help
Chooses the cipher in the order of AES128-SHA, AES256-SHA, RC4-SHA.
This mode is a balance between speed and security and is the default.
config CONFIG_SSL_PROT_HIGH
bool "High"
help
Chooses the cipher in the order of AES256-SHA, AES128-SHA, RC4-SHA.
This will use the strongest cipher(s) at the cost of speed.
endchoice
config CONFIG_SSL_USE_DEFAULT_KEY
bool "Enable default key"
depends on !CONFIG_SSL_SKELETON_MODE
default y
help
Some applications will not require the default private key/certificate
that is built in. This is one way to save on a couple of kB's if an
external private key/certificate is used.
The advantage of a built-in private key/certificate is that no file
system is required for access.
However this private key/certificate can never be changed (without a
code update).
This mode is enabled by default. Disable this mode if the
built-in key/certificate is not used.
config CONFIG_SSL_ENABLE_V23_HANDSHAKE
bool "Enable v23 Handshake"
default y
help
Some browsers use the v23 handshake client hello message
(an SSL2 format message which all SSL servers can understand).
It may be used if SSL2 is enabled in the browser.
Since this feature takes a kB or so, this feature may be disabled - at
the risk of making it incompatible with some browsers (IE6 is ok,
Firefox 1.5 and below use it).
Disable if backwards compatibility is not an issue (i.e. the client is
always using TLS1.0)
config CONFIG_SSL_HAS_PEM
bool "Enable PEM"
default n if !CONFIG_SSL_FULL_MODE
default y if CONFIG_SSL_FULL_MODE
depends on !CONFIG_SSL_SKELETON_MODE
help
Enable the use of PEM format for certificates and private keys.
PEM is not normally needed - PEM files can be converted into DER files
quite easily. However they have the convenience of allowing multiple
certificates/keys in the same file.
This feature will add a couple of kB to the library.
Disable if PEM is not used (which will be in most cases).
config CONFIG_SSL_USE_PKCS12
bool "Use PKCS8/PKCS12"
default n if !CONFIG_SSL_FULL_MODE
default y if CONFIG_SSL_FULL_MODE
depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
help
PKCS#12 certificates combine private keys and certificates together in
one file.
PKCS#8 private keys are also suppported (as it is a subset of PKCS#12).
The decryption of these certificates uses RC4-128 (and these
certificates must be encrypted using this cipher). The actual
algorithm is "PBE-SHA1-RC4-128".
Disable if PKCS#12 is not used (which will be in most cases).
config CONFIG_SSL_EXPIRY_TIME
int "Session expiry time (in hours)"
depends on !CONFIG_SSL_SKELETON_MODE
default 24
help
The time (in hours) before a session expires.
A longer time means that the expensive parts of a handshake don't
need to be run when a client reconnects later.
The default is 1 day.
config CONFIG_X509_MAX_CA_CERTS
int "Maximum number of certificate authorites"
default 4
depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
help
Determines the number of CA's allowed.
Increase this figure if more trusted sites are allowed. Each
certificate adds about 300 bytes (when added).
The default is to allow four certification authorities.
config CONFIG_SSL_MAX_CERTS
int "Maximum number of chained certificates"
default 2
help
Determines the number of certificates used in a certificate
chain. The chain length must be at least 1.
Increase this figure if more certificates are to be added to the
chain. Each certificate adds about 300 bytes (when added).
The default is to allow one certificate + 1 certificate in the chain
(which may be the certificate authority certificate).
config CONFIG_SSL_CTX_MUTEXING
bool "Enable SSL_CTX mutexing"
default n
help
Normally mutexing is not required - each SSL_CTX object can deal with
many SSL objects (as long as each SSL_CTX object is using a single
thread).
If the SSL_CTX object is not thread safe e.g. the case where a
new thread is created for each SSL object, then mutexing is required.
Select y when a mutex on the SSL_CTX object is required.
config CONFIG_USE_DEV_URANDOM
bool "Use /dev/urandom"
default y
depends on !CONFIG_PLATFORM_WIN32
help
Use /dev/urandom. Otherwise a custom RNG is used.
This will be the default on most Linux systems.
config CONFIG_WIN32_USE_CRYPTO_LIB
bool "Use Win32 Crypto Library"
default y if !CONFIG_VISUAL_STUDIO_6_0
default n if CONFIG_VISUAL_STUDIO_6_0
depends on CONFIG_PLATFORM_WIN32
help
Microsoft produce a Crypto API which requires the Platform SDK to be
installed. It's used for the RNG.
This will be the default on most Win32 systems. If using Visual Studio
6.0, then the SDK containing the crypto libraries must be used.
config CONFIG_OPENSSL_COMPATIBLE
bool "Enable openssl API compatibility"
default n
help
To ease the porting of openssl applications, a subset of the openssl
API is wrapped around the axTLS API.
Note: not all the API is implemented, so parts may still break. And
it's definitely not 100% compatible.
config CONFIG_PERFORMANCE_TESTING
bool "Build the bigint performance test tool"
default n
help
Used for performance testing of bigint.
This is a testing tool and is normally disabled.
config CONFIG_SSL_TEST
bool "Build the SSL testing tool"
default n
depends on CONFIG_SSL_FULL_MODE
help
Used for sanity checking the SSL handshaking.
This is a testing tool and is normally disabled.
endmenu

101
ssl/Makefile Normal file
View File

@ -0,0 +1,101 @@
#
# Copyright(C) 2007 Cameron Rich
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser General Public License
# along with this library; 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: libs
ifdef CONFIG_PERFORMANCE_TESTING
$(MAKE) -C test
else
ifdef CONFIG_SSL_TEST
$(MAKE) -C test
endif
endif
ifndef CONFIG_PLATFORM_WIN32
TARGET1=../$(STAGE)/libaxtls.a
BASETARGET=libaxtls.so
ifdef CONFIG_PLATFORM_CYGWIN
TARGET2=../$(STAGE)/libaxtls.dll.a
else
TARGET2=../$(STAGE)/$(LIBMINOR)
endif
# shared library major/minor numbers
LIBMAJOR=$(BASETARGET).1
LIBMINOR=$(BASETARGET).1.1
else
TARGET1=axtls.lib
TARGET2=../$(STAGE)/axtls.dll
STATIC_LIB=../$(STAGE)/axtls.static.lib
endif
libs: $(TARGET1) $(TARGET2)
OBJ=\
aes.o \
asn1.o \
bigint.o \
crypto_misc.o \
hmac.o \
os_port.o \
loader.o \
md5.o \
openssl.o \
p12.o \
rsa.o \
rc4.o \
sha1.o \
tls1.o \
tls1_svr.o \
tls1_clnt.o
include ../config/makefile.post
ifndef CONFIG_PLATFORM_WIN32 # Linux/Unix/Cygwin
$(TARGET1) : $(OBJ)
$(AR) -r $@ $(OBJ)
$(TARGET2) : $(OBJ)
ifndef CONFIG_PLATFORM_CYGWIN
$(LD) $(LDFLAGS) $(LDSHARED) -Wl,-soname,$(LIBMAJOR) -o ../$(STAGE)/$(LIBMINOR) $(OBJ)
cd ../$(STAGE); ln -sf $(LIBMINOR) $(LIBMAJOR); ln -sf $(LIBMAJOR) $(BASETARGET); cd -
else
$(LD) $(LDFLAGS) $(LDSHARED) -o ../$(STAGE)/cygaxtls.dll \
-Wl,--out-implib=../$(STAGE)/libaxtls.dll.a \
-Wl,--export-all-symbols \
-Wl,--enable-auto-import $(OBJ)
endif
else # Win32
$(TARGET1) : $(OBJ)
$(AR) /out:$@ $(OBJ)
$(TARGET2) : $(OBJ)
cp $(TARGET1) $(STATIC_LIB)
$(LD) $(LDFLAGS) $(LDSHARED) /out:$@ $(OBJ)
endif
clean::
$(MAKE) -C test clean
-@rm -f ../$(STAGE)/* *.a *.lib

444
ssl/aes.c Normal file
View File

@ -0,0 +1,444 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* AES implementation - this is a small code version. There are much faster
* versions around but they are much larger in size (i.e. they use large
* submix tables).
*/
#include <string.h>
#include "crypto.h"
/* all commented out in skeleton mode */
#ifndef CONFIG_SSL_SKELETON_MODE
#define rot1(x) (((x) << 24) | ((x) >> 8))
#define rot2(x) (((x) << 16) | ((x) >> 16))
#define rot3(x) (((x) << 8) | ((x) >> 24))
/*
* This cute trick does 4 'mul by two' at once. Stolen from
* Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
* a standard graphics trick
* The key to this is that we need to xor with 0x1b if the top bit is set.
* a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
* b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
* c 0000 0001 0000 0000 we then subtract (c) from (b)
* d 0111 1111 0000 0000 and now we and with our mask
* e 0001 1011 0000 0000
*/
#define mt 0x80808080
#define ml 0x7f7f7f7f
#define mh 0xfefefefe
#define mm 0x1b1b1b1b
#define mul2(x,t) ((t)=((x)&mt), \
((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
#define inv_mix_col(x,f2,f4,f8,f9) (\
(f2)=mul2(x,f2), \
(f4)=mul2(f2,f4), \
(f8)=mul2(f4,f8), \
(f9)=(x)^(f8), \
(f8)=((f2)^(f4)^(f8)), \
(f2)^=(f9), \
(f4)^=(f9), \
(f8)^=rot3(f2), \
(f8)^=rot2(f4), \
(f8)^rot1(f9))
/*
* AES S-box
*/
static const uint8_t aes_sbox[256] =
{
0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
};
/*
* AES is-box
*/
static const uint8_t aes_isbox[256] =
{
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
};
static const unsigned char Rcon[30]=
{
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
0xb3,0x7d,0xfa,0xef,0xc5,0x91,
};
/* ----- static functions ----- */
static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
x^8+x^4+x^3+x+1 */
static unsigned char AES_xtime(uint32_t x)
{
return x = (x&0x80) ? (x<<1)^0x1b : x<<1;
}
/**
* Set up AES with the key/iv and cipher size.
*/
void AES_set_key(AES_CTX *ctx, const uint8_t *key,
const uint8_t *iv, AES_MODE mode)
{
int i, ii;
uint32_t *W, tmp, tmp2;
const unsigned char *ip;
int words;
switch (mode)
{
case AES_MODE_128:
i = 10;
words = 4;
break;
case AES_MODE_256:
i = 14;
words = 8;
break;
default: /* fail silently */
return;
}
ctx->rounds = i;
ctx->key_size = words;
W = ctx->ks;
for (i = 0; i < words; i+=2)
{
W[i+0]= ((uint32_t)key[ 0]<<24)|
((uint32_t)key[ 1]<<16)|
((uint32_t)key[ 2]<< 8)|
((uint32_t)key[ 3] );
W[i+1]= ((uint32_t)key[ 4]<<24)|
((uint32_t)key[ 5]<<16)|
((uint32_t)key[ 6]<< 8)|
((uint32_t)key[ 7] );
key += 8;
}
ip = Rcon;
ii = 4 * (ctx->rounds+1);
for (i = words; i<ii; i++)
{
tmp = W[i-1];
if ((i % words) == 0)
{
tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
tmp=tmp2^(((unsigned int)*ip)<<24);
ip++;
}
if ((words == 8) && ((i % words) == 4))
{
tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
tmp=tmp2;
}
W[i]=W[i-words]^tmp;
}
/* copy the iv across */
memcpy(ctx->iv, iv, 16);
}
/**
* Change a key for decryption.
*/
void AES_convert_key(AES_CTX *ctx)
{
int i;
uint32_t *k,w,t1,t2,t3,t4;
k = ctx->ks;
k += 4;
for (i= ctx->rounds*4; i > 4; i--)
{
w= *k;
w = inv_mix_col(w,t1,t2,t3,t4);
*k++ =w;
}
}
/**
* Encrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{
int i;
uint32_t tin[4], tout[4], iv[4];
memcpy(iv, ctx->iv, AES_IV_SIZE);
for (i = 0; i < 4; i++)
tout[i] = ntohl(iv[i]);
for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
{
uint32_t msg_32[4];
uint32_t out_32[4];
memcpy(msg_32, msg, AES_BLOCKSIZE);
msg += AES_BLOCKSIZE;
for (i = 0; i < 4; i++)
tin[i] = ntohl(msg_32[i])^tout[i];
AES_encrypt(ctx, tin);
for (i = 0; i < 4; i++)
{
tout[i] = tin[i];
out_32[i] = htonl(tout[i]);
}
memcpy(out, out_32, AES_BLOCKSIZE);
out += AES_BLOCKSIZE;
}
for (i = 0; i < 4; i++)
iv[i] = htonl(tout[i]);
memcpy(ctx->iv, iv, AES_IV_SIZE);
}
/**
* Decrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{
int i;
uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
memcpy(iv, ctx->iv, AES_IV_SIZE);
for (i = 0; i < 4; i++)
xor[i] = ntohl(iv[i]);
for (length -= 16; length >= 0; length -= 16)
{
uint32_t msg_32[4];
uint32_t out_32[4];
memcpy(msg_32, msg, AES_BLOCKSIZE);
msg += AES_BLOCKSIZE;
for (i = 0; i < 4; i++)
{
tin[i] = ntohl(msg_32[i]);
data[i] = tin[i];
}
AES_decrypt(ctx, data);
for (i = 0; i < 4; i++)
{
tout[i] = data[i]^xor[i];
xor[i] = tin[i];
out_32[i] = htonl(tout[i]);
}
memcpy(out, out_32, AES_BLOCKSIZE);
out += AES_BLOCKSIZE;
}
for (i = 0; i < 4; i++)
iv[i] = htonl(xor[i]);
memcpy(ctx->iv, iv, AES_IV_SIZE);
}
/**
* Encrypt a single block (16 bytes) of data
*/
static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
{
/* To make this code smaller, generate the sbox entries on the fly.
* This will have a really heavy effect upon performance.
*/
uint32_t tmp[4];
uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
int curr_rnd;
int rounds = ctx->rounds;
const uint32_t *k = ctx->ks;
/* Pre-round key addition */
for (row = 0; row < 4; row++)
data[row] ^= *(k++);
/* Encrypt one block. */
for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
{
/* Perform ByteSub and ShiftRow operations together */
for (row = 0; row < 4; row++)
{
a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
/* Perform MixColumn iff not last round */
if (curr_rnd < (rounds - 1))
{
tmp1 = a0 ^ a1 ^ a2 ^ a3;
old_a0 = a0;
a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
}
tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
}
/* KeyAddition - note that it is vital that this loop is separate from
the MixColumn operation, which must be atomic...*/
for (row = 0; row < 4; row++)
data[row] = tmp[row] ^ *(k++);
}
}
/**
* Decrypt a single block (16 bytes) of data
*/
static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
{
uint32_t tmp[4];
uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
uint32_t a0, a1, a2, a3, row;
int curr_rnd;
int rounds = ctx->rounds;
const uint32_t *k = ctx->ks + ((rounds+1)*4);
/* pre-round key addition */
for (row=4; row > 0;row--)
data[row-1] ^= *(--k);
/* Decrypt one block */
for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
{
/* Perform ByteSub and ShiftRow operations together */
for (row = 4; row > 0; row--)
{
a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
a3 = aes_isbox[(data[row%4])&0xFF];
/* Perform MixColumn iff not last round */
if (curr_rnd<(rounds-1))
{
/* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
are quite large compared to encryption; this
operation slows decryption down noticeably. */
xt0 = AES_xtime(a0^a1);
xt1 = AES_xtime(a1^a2);
xt2 = AES_xtime(a2^a3);
xt3 = AES_xtime(a3^a0);
xt4 = AES_xtime(xt0^xt1);
xt5 = AES_xtime(xt1^xt2);
xt6 = AES_xtime(xt4^xt5);
xt0 ^= a1^a2^a3^xt4^xt6;
xt1 ^= a0^a2^a3^xt5^xt6;
xt2 ^= a0^a1^a3^xt4^xt6;
xt3 ^= a0^a1^a2^xt5^xt6;
tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
}
else
tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
}
for (row = 4; row > 0; row--)
data[row-1] = tmp[row-1] ^ *(--k);
}
}
#endif

864
ssl/asn1.c Normal file
View File

@ -0,0 +1,864 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file asn1.c
*
* Some primitive asn methods for extraction rsa modulus information. It also
* is used for retrieving information from X.509 certificates.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "crypto.h"
#define SIG_OID_PREFIX_SIZE 8
#define SIG_TYPE_MD2 0x02
#define SIG_TYPE_MD5 0x04
#define SIG_TYPE_SHA1 0x05
/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
{
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
};
/* CN, O, OU */
static const uint8_t g_dn_types[] = { 3, 10, 11 };
static int get_asn1_length(const uint8_t *buf, int *offset)
{
int len, i;
if (!(buf[*offset] & 0x80)) /* short form */
{
len = buf[(*offset)++];
}
else /* long form */
{
int length_bytes = buf[(*offset)++]&0x7f;
len = 0;
for (i = 0; i < length_bytes; i++)
{
len <<= 8;
len += buf[(*offset)++];
}
}
return len;
}
/**
* Skip the ASN1.1 object type and its length. Get ready to read the object's
* data.
*/
int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
{
if (buf[*offset] != obj_type)
return X509_NOT_OK;
(*offset)++;
return get_asn1_length(buf, offset);
}
/**
* Skip over an ASN.1 object type completely. Get ready to read the next
* object.
*/
int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
{
int len;
if (buf[*offset] != obj_type)
return X509_NOT_OK;
(*offset)++;
len = get_asn1_length(buf, offset);
*offset += len;
return 0;
}
/**
* Read an integer value for ASN.1 data
* Note: This function allocates memory which must be freed by the user.
*/
int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
{
int len;
if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
goto end_int_array;
*object = (uint8_t *)malloc(len);
memcpy(*object, &buf[*offset], len);
*offset += len;
end_int_array:
return len;
}
/**
* Get all the RSA private key specifics from an ASN.1 encoded file
*/
int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
{
int offset = 7;
uint8_t *modulus, *priv_exp, *pub_exp;
int mod_len, priv_len, pub_len;
#ifdef CONFIG_BIGINT_CRT
uint8_t *p, *q, *dP, *dQ, *qInv;
int p_len, q_len, dP_len, dQ_len, qInv_len;
#endif
/* not in der format */
if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: This is not a valid ASN.1 file\n");
#endif
return X509_INVALID_PRIV_KEY;
}
/* initialise the RNG */
RNG_initialize(buf, len);
mod_len = asn1_get_int(buf, &offset, &modulus);
pub_len = asn1_get_int(buf, &offset, &pub_exp);
priv_len = asn1_get_int(buf, &offset, &priv_exp);
if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
return X509_INVALID_PRIV_KEY;
#ifdef CONFIG_BIGINT_CRT
p_len = asn1_get_int(buf, &offset, &p);
q_len = asn1_get_int(buf, &offset, &q);
dP_len = asn1_get_int(buf, &offset, &dP);
dQ_len = asn1_get_int(buf, &offset, &dQ);
qInv_len = asn1_get_int(buf, &offset, &qInv);
if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
return X509_INVALID_PRIV_KEY;
RSA_priv_key_new(rsa_ctx,
modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
free(p);
free(q);
free(dP);
free(dQ);
free(qInv);
#else
RSA_priv_key_new(rsa_ctx,
modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
#endif
free(modulus);
free(priv_exp);
free(pub_exp);
return X509_OK;
}
/**
* Get the time of a certificate. Ignore hours/minutes/seconds.
*/
static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
{
int ret = X509_NOT_OK, len, t_offset;
struct tm tm;
if (buf[(*offset)++] != ASN1_UTC_TIME)
goto end_utc_time;
len = get_asn1_length(buf, offset);
t_offset = *offset;
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 */
{
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');
*t = mktime(&tm);
*offset += len;
ret = X509_OK;
end_utc_time:
return ret;
}
/**
* Get the version type of a certificate (which we don't actually care about)
*/
static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK;
(*offset) += 2; /* get past explicit tag */
if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
goto end_version;
ret = X509_OK;
end_version:
return ret;
}
/**
* Retrieve the notbefore and notafter certificate times.
*/
static int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
}
/**
* Get the components of a distinguished name
*/
static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
{
int dn_type = 0;
int len;
if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
goto end_oid;
/* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
components we are interested in. */
if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
dn_type = buf[(*offset)++];
else
{
*offset += len; /* skip over it */
}
end_oid:
return dn_type;
}
/**
* Obtain an ASN.1 printable string type.
*/
static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
{
int len = X509_NOT_OK;
/* some certs have this awful crud in them for some reason */
if (buf[*offset] != ASN1_PRINTABLE_STR &&
buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR)
goto end_pnt_str;
(*offset)++;
len = get_asn1_length(buf, offset);
*str = (char *)malloc(len+1); /* allow for null */
memcpy(*str, &buf[*offset], len);
(*str)[len] = 0; /* null terminate */
*offset += len;
end_pnt_str:
return len;
}
/**
* Get the subject name (or the issuer) of a certificate.
*/
static int asn1_name(const uint8_t *cert, int *offset, char *dn[])
{
int ret = X509_NOT_OK;
int dn_type;
char *tmp = NULL;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
goto end_name;
while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
{
int i, found = 0;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
(dn_type = asn1_get_oid_x520(cert, offset)) < 0)
goto end_name;
if (asn1_get_printable_str(cert, offset, &tmp) < 0)
{
free(tmp);
goto end_name;
}
/* find the distinguished named type */
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
if (dn_type == g_dn_types[i])
{
if (dn[i] == NULL)
{
dn[i] = tmp;
found = 1;
break;
}
}
}
if (found == 0) /* not found so get rid of it */
{
free(tmp);
}
}
ret = X509_OK;
end_name:
return ret;
}
/**
* Read the modulus and public exponent of a certificate.
*/
static int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK, mod_len, pub_len;
uint8_t *modulus, *pub_exp;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
goto end_pub_key;
(*offset)++;
if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
goto end_pub_key;
mod_len = asn1_get_int(cert, offset, &modulus);
pub_len = asn1_get_int(cert, offset, &pub_exp);
RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
free(modulus);
free(pub_exp);
ret = X509_OK;
end_pub_key:
return ret;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Read the signature of the certificate.
*/
static int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK;
if (cert[(*offset)++] != ASN1_BIT_STRING)
goto end_sig;
x509_ctx->sig_len = get_asn1_length(cert, offset);
x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
*offset += x509_ctx->sig_len;
ret = X509_OK;
end_sig:
return ret;
}
/*
* Compare 2 distinguished name components for equality
* @return 0 if a match
*/
static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
{
int ret = 1;
if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
err_no_match:
return ret;
}
/**
* Clean up all of the CA certificates.
*/
void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
{
int i = 0;
while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
x509_free(ca_cert_ctx->cert[i]);
ca_cert_ctx->cert[i++] = NULL;
}
free(ca_cert_ctx);
}
/*
* Compare 2 distinguished names for equality
* @return 0 if a match
*/
static int asn1_compare_dn(char * const dn1[], char * const dn2[])
{
int i;
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
if (asn1_compare_dn_comp(dn1[i], dn2[i]))
{
return 1;
}
}
return 0; /* all good */
}
/**
* Retrieve the signature from a certificate.
*/
const uint8_t *x509_get_signature(const uint8_t *asn1_sig, int *len)
{
int offset = 0;
const uint8_t *ptr = NULL;
if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
goto end_get_sig;
if (asn1_sig[offset++] != ASN1_OCTET_STRING)
goto end_get_sig;
*len = get_asn1_length(asn1_sig, &offset);
ptr = &asn1_sig[offset]; /* all ok */
end_get_sig:
return ptr;
}
#endif
/**
* Read the signature type of the certificate. We only support RSA-MD5 and
* RSA-SHA1 signature types.
*/
static int asn1_signature_type(const uint8_t *cert,
int *offset, X509_CTX *x509_ctx)
{
int ret = X509_NOT_OK, len;
if (cert[(*offset)++] != ASN1_OID)
goto end_check_sig;
len = get_asn1_length(cert, offset);
if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
goto end_check_sig; /* unrecognised cert type */
x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
*offset += len;
if (asn1_skip_obj(cert, offset, ASN1_NULL))
goto end_check_sig;
ret = X509_OK;
end_check_sig:
return ret;
}
/**
* Construct a new x509 object.
* @return 0 if ok. < 0 if there was a problem.
*/
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
{
int begin_tbs, end_tbs;
int ret = X509_NOT_OK, offset = 0, cert_size = 0;
X509_CTX *x509_ctx;
BI_CTX *bi_ctx;
*ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
x509_ctx = *ctx;
/* get the certificate size */
asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);
if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
begin_tbs = offset; /* start of the tbs */
end_tbs = begin_tbs; /* work out the end of the tbs */
asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
{
if (asn1_version(cert, &offset, x509_ctx))
goto end_cert;
}
if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
goto end_cert;
/* make sure the signature is ok */
if (asn1_signature_type(cert, &offset, x509_ctx))
{
ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
goto end_cert;
}
if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
asn1_validity(cert, &offset, x509_ctx) ||
asn1_name(cert, &offset, x509_ctx->cert_dn) ||
asn1_public_key(cert, &offset, x509_ctx))
goto end_cert;
bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
/* use the appropriate signature algorithm (either SHA1 or MD5) */
if (x509_ctx->sig_type == SIG_TYPE_MD5)
{
MD5_CTX md5_ctx;
uint8_t md5_dgst[MD5_SIZE];
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
MD5Final(&md5_ctx, md5_dgst);
x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
}
else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
{
SHA1_CTX sha_ctx;
uint8_t sha_dgst[SHA1_SIZE];
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
SHA1Final(&sha_ctx, sha_dgst);
x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
}
offset = end_tbs; /* skip the v3 data */
if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
asn1_signature(cert, &offset, x509_ctx))
goto end_cert;
#endif
if (len)
{
*len = cert_size;
}
ret = X509_OK;
end_cert:
#ifdef CONFIG_SSL_FULL_MODE
if (ret)
{
printf("Error: Invalid X509 ASN.1 file\n");
}
#endif
return ret;
}
/**
* Free an X.509 object's resources.
*/
void x509_free(X509_CTX *x509_ctx)
{
X509_CTX *next;
int i;
if (x509_ctx == NULL) /* if already null, then don't bother */
return;
for (i = 0; i < X509_NUM_DN_TYPES; i++)
{
free(x509_ctx->ca_cert_dn[i]);
free(x509_ctx->cert_dn[i]);
}
free(x509_ctx->signature);
#ifdef CONFIG_SSL_CERT_VERIFICATION
if (x509_ctx->digest)
{
bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
}
#endif
RSA_free(x509_ctx->rsa_ctx);
next = x509_ctx->next;
free(x509_ctx);
x509_free(next); /* clear the chain */
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Do some basic checks on the certificate chain.
*
* Certificate verification consists of a number of checks:
* - A root certificate exists in the certificate store.
* - The date of the certificate is after the start date.
* - The date of the certificate is before the finish date.
* - The certificate chain is valid.
* - That the certificate(s) are not self-signed.
* - The signature of the certificate is valid.
*/
int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
{
int ret = X509_OK, i = 0;
bigint *cert_sig;
X509_CTX *next_cert = NULL;
BI_CTX *ctx;
bigint *mod, *expn;
struct timeval tv;
int match_ca_cert = 0;
if (cert == NULL || ca_cert_ctx == NULL)
{
ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
goto end_verify;
}
/* last cert in the chain - look for a trusted cert */
if (cert->next == NULL)
{
while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
if (asn1_compare_dn(cert->ca_cert_dn,
ca_cert_ctx->cert[i]->cert_dn) == 0)
{
match_ca_cert = 1;
break;
}
i++;
}
if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
{
next_cert = ca_cert_ctx->cert[i];
}
else /* trusted cert not found */
{
ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
goto end_verify;
}
}
else
{
next_cert = cert->next;
}
gettimeofday(&tv, NULL);
/* check the not before date */
if (tv.tv_sec < cert->not_before)
{
ret = X509_VFY_ERROR_NOT_YET_VALID;
goto end_verify;
}
/* check the not after date */
if (tv.tv_sec > cert->not_after)
{
ret = X509_VFY_ERROR_EXPIRED;
goto end_verify;
}
/* check the chain integrity */
if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn))
{
ret = X509_VFY_ERROR_INVALID_CHAIN;
goto end_verify;
}
/* check for self-signing */
if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
{
ret = X509_VFY_ERROR_SELF_SIGNED;
goto end_verify;
}
/* check the signature */
ctx = cert->rsa_ctx->bi_ctx;
mod = next_cert->rsa_ctx->m;
expn = next_cert->rsa_ctx->e;
cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len,
bi_clone(ctx, mod), bi_clone(ctx, expn));
if (cert_sig)
{
ret = cert->digest ? /* check the signature */
bi_compare(cert_sig, cert->digest) :
X509_VFY_ERROR_UNSUPPORTED_DIGEST;
bi_free(ctx, cert_sig);
if (ret)
goto end_verify;
}
else
{
ret = X509_VFY_ERROR_BAD_SIGNATURE;
goto end_verify;
}
/* go down the certificate chain using recursion. */
if (ret == 0 && cert->next)
{
ret = x509_verify(ca_cert_ctx, next_cert);
}
end_verify:
return ret;
}
#endif
#if defined (CONFIG_SSL_FULL_MODE)
/**
* Used for diagnostics.
*/
void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
{
if (cert == NULL)
return;
printf("---------------- CERT DEBUG ----------------\n");
printf("* CA Cert Distinguished Name\n");
if (cert->ca_cert_dn[X509_COMMON_NAME])
{
printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]);
}
if (cert->ca_cert_dn[X509_ORGANIZATION])
{
printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]);
}
if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE])
{
printf("Organizational Unit (OU): %s\n",
cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]);
}
printf("* Cert Distinguished Name\n");
if (cert->cert_dn[X509_COMMON_NAME])
{
printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]);
}
if (cert->cert_dn[X509_ORGANIZATION])
{
printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]);
}
if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE])
{
printf("Organizational Unit (OU): %s\n",
cert->cert_dn[X509_ORGANIZATIONAL_TYPE]);
}
printf("Not Before:\t\t%s", ctime(&cert->not_before));
printf("Not After:\t\t%s", ctime(&cert->not_after));
printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8);
printf("Sig Type:\t\t");
switch (cert->sig_type)
{
case SIG_TYPE_MD5:
printf("MD5\n");
break;
case SIG_TYPE_SHA1:
printf("SHA1\n");
break;
case SIG_TYPE_MD2:
printf("MD2\n");
break;
default:
printf("Unrecognized: %d\n", cert->sig_type);
break;
}
printf("Verify:\t\t\t");
if (ca_cert_ctx)
{
x509_display_error(x509_verify(ca_cert_ctx, cert));
}
printf("\n");
#if 0
print_blob("Signature", cert->signature, cert->sig_len);
bi_print("Modulus", cert->rsa_ctx->m);
bi_print("Pub Exp", cert->rsa_ctx->e);
#endif
if (ca_cert_ctx)
{
x509_print(ca_cert_ctx, cert->next);
}
}
void x509_display_error(int error)
{
switch (error)
{
case X509_NOT_OK:
printf("X509 not ok");
break;
case X509_VFY_ERROR_NO_TRUSTED_CERT:
printf("No trusted cert is available");
break;
case X509_VFY_ERROR_BAD_SIGNATURE:
printf("Bad signature");
break;
case X509_VFY_ERROR_NOT_YET_VALID:
printf("Cert is not yet valid");
break;
case X509_VFY_ERROR_EXPIRED:
printf("Cert has expired");
break;
case X509_VFY_ERROR_SELF_SIGNED:
printf("Cert is self-signed");
break;
case X509_VFY_ERROR_INVALID_CHAIN:
printf("Chain is invalid (check order of certs)");
break;
case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
printf("Unsupported digest");
break;
case X509_INVALID_PRIV_KEY:
printf("Invalid private key");
break;
}
}
#endif /* CONFIG_SSL_FULL_MODE */

1506
ssl/bigint.c Normal file

File diff suppressed because it is too large Load Diff

93
ssl/bigint.h Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BIGINT_HEADER
#define BIGINT_HEADER
#include "config.h"
/* enable features based on a 'super-set' capbaility. */
#if defined(CONFIG_SSL_FULL_MODE)
#define CONFIG_SSL_ENABLE_CLIENT
#define CONFIG_SSL_CERT_VERIFICATION
#elif defined(CONFIG_SSL_ENABLE_CLIENT)
#define CONFIG_SSL_CERT_VERIFICATION
#endif
#include "os_port.h"
#include "bigint_impl.h"
#ifndef CONFIG_BIGINT_CHECK_ON
#define check(A) /**< disappears in normal production mode */
#endif
BI_CTX *bi_initialize(void);
void bi_terminate(BI_CTX *ctx);
void bi_permanent(bigint *bi);
void bi_depermanent(bigint *bi);
void bi_free(BI_CTX *ctx, bigint *bi);
bigint *bi_copy(bigint *bi);
bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
bigint *int_to_bi(BI_CTX *ctx, comp i);
/* the functions that actually do something interesting */
bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
bigint *bib, int *is_negative);
bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
int bi_compare(bigint *bia, bigint *bib);
void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
void bi_free_mod(BI_CTX *ctx, int mod_offset);
#ifdef CONFIG_SSL_FULL_MODE
void bi_print(const char *label, bigint *bi);
bigint *bi_str_import(BI_CTX *ctx, const char *data);
#endif
/**
* @def bi_mod
* Find the residue of B. bi_set_mod() must be called before hand.
*/
#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
/**
* bi_residue() is technically the same as bi_mod(), but it uses the
* appropriate reduction technique (which is bi_mod() when doing classical
* reduction).
*/
#if defined(CONFIG_BIGINT_MONTGOMERY)
#define bi_residue(A, B) bi_mont(A, B)
bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
#elif defined(CONFIG_BIGINT_BARRETT)
#define bi_residue(A, B) bi_barrett(A, B)
bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
#define bi_residue(A, B) bi_mod(A, B)
#endif
#ifdef CONFIG_BIGINT_SQUARE
bigint *bi_square(BI_CTX *ctx, bigint *bi);
#else
#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
#endif
#endif

105
ssl/bigint_impl.h Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BIGINT_IMPL_HEADER
#define BIGINT_IMPL_HEADER
/* Maintain a number of precomputed variables when doing reduction */
#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
#ifdef CONFIG_BIGINT_CRT
#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
#define BIGINT_Q_OFFSET 2 /**< q module offset. */
#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
#else
#define BIGINT_NUM_MODS 1
#endif
/* Architecture specific functions for big ints */
#ifdef WIN32
#define COMP_RADIX 4294967296i64
#define COMP_BIG_MSB 0x8000000000000000i64
#else
#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */
#endif
#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */
#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */
#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */
typedef uint32_t comp; /**< A single precision component. */
typedef uint64_t long_comp; /**< A double precision component. */
typedef int64_t slong_comp; /**< A signed double precision component. */
/**
* @struct _bigint
* @brief A big integer basic object
*/
struct _bigint
{
struct _bigint* next; /**< The next bigint in the cache. */
short size; /**< The number of components in this bigint. */
short max_comps; /**< The heapsize allocated for this bigint */
int refs; /**< An internal reference count. */
comp* comps; /**< A ptr to the actual component data */
};
typedef struct _bigint bigint; /**< An alias for _bigint */
/**
* Maintains the state of the cache, and a number of variables used in
* reduction.
*/
typedef struct /**< A big integer "session" context. */
{
bigint *active_list; /**< Bigints currently used. */
bigint *free_list; /**< Bigints not used. */
bigint *bi_radix; /**< The radix used. */
bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
#if defined(CONFIG_BIGINT_MONTGOMERY)
bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
comp N0_dash[BIGINT_NUM_MODS];
#elif defined(CONFIG_BIGINT_BARRETT)
bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
#endif
bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
bigint **g; /**< Used by sliding-window. */
int window; /**< The size of the sliding window */
int active_count; /**< Number of active bigints. */
int free_count; /**< Number of free bigints. */
#ifdef CONFIG_BIGINT_MONTGOMERY
uint8_t use_classical; /**< Use classical reduction. */
#endif
uint8_t mod_offset; /**< The mod offset we are using */
} BI_CTX;
#ifndef WIN32
#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
#endif
#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
#define V1 v->comps[v->size-1] /**< v1 for division */
#define V2 v->comps[v->size-2] /**< v2 for division */
#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */
#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */
#endif

43
ssl/cert.h Normal file
View File

@ -0,0 +1,43 @@
unsigned char default_certificate[] = {
0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xf1,
0xc3, 0x87, 0xc0, 0xd4, 0xf4, 0x57, 0xc3, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34,
0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61,
0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36,
0x30, 0x37, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33,
0x33, 0x31, 0x30, 0x32, 0x33, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a,
0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81,
0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
0x81, 0x81, 0x00, 0xd8, 0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5,
0xfd, 0x0b, 0xa8, 0xa8, 0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c,
0xb5, 0xd9, 0xbc, 0xc6, 0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8,
0x29, 0x48, 0x0e, 0x7b, 0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f,
0x38, 0xe5, 0xb5, 0xb7, 0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3,
0x40, 0x1e, 0xf9, 0x91, 0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e,
0xdc, 0xf6, 0xaa, 0x1c, 0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73,
0xd9, 0x09, 0x05, 0x4c, 0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7,
0x14, 0x91, 0x44, 0xfc, 0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba,
0x8c, 0xc3, 0x74, 0x39, 0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4,
0x40, 0x95, 0x8c, 0xc0, 0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02,
0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x0b,
0x47, 0x24, 0x52, 0x7d, 0xb6, 0x63, 0x78, 0xbc, 0x80, 0xdd, 0x87, 0x6c,
0x90, 0x4c, 0x33, 0xc3, 0x5c, 0xa7, 0x97, 0x09, 0x1c, 0x09, 0x4f, 0x9b,
0x6e, 0xb3, 0x5a, 0x3e, 0x46, 0x92, 0x1a, 0xc7, 0x87, 0x15, 0x59, 0xe1,
0x88, 0x5c, 0xce, 0x6a, 0xe2, 0x96, 0xaa, 0x32, 0xec, 0xc2, 0xed, 0x78,
0x8b, 0xe0, 0x90, 0x66, 0x93, 0x14, 0xc3, 0x98, 0xab, 0x33, 0x35, 0xd3,
0x7d, 0x5d, 0x51, 0x0a, 0x9c, 0xb9, 0x10, 0x58, 0x47, 0x7a, 0x98, 0x95,
0x64, 0xff, 0x4c, 0x5d, 0x82, 0x19, 0xf9, 0xea, 0x0f, 0x5e, 0x9a, 0xcb,
0x32, 0x27, 0x64, 0xca, 0x6f, 0x58, 0x8a, 0xd0, 0xc0, 0x36, 0xf4, 0xb9,
0x63, 0x34, 0xa5, 0xda, 0x36, 0x50, 0x36, 0x49, 0xd2, 0xb7, 0x3a, 0x21,
0x33, 0x5b, 0x3e, 0xd6, 0x5f, 0x0c, 0x99, 0x83, 0xb7, 0xb2, 0xf7, 0x8b,
0x44, 0xc4, 0x5e, 0x73, 0x41, 0xa9, 0x02
};
unsigned int default_certificate_len = 475;

285
ssl/crypto.h Normal file
View File

@ -0,0 +1,285 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* @file crypto.h
*/
#ifndef HEADER_CRYPTO_H
#define HEADER_CRYPTO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "bigint.h"
/**************************************************************************
* AES declarations
**************************************************************************/
#define AES_MAXROUNDS 14
#define AES_BLOCKSIZE 16
#define AES_IV_SIZE 16
typedef struct aes_key_st
{
uint16_t rounds;
uint16_t key_size;
uint32_t ks[(AES_MAXROUNDS+1)*8];
uint8_t iv[AES_IV_SIZE];
} AES_CTX;
typedef enum
{
AES_MODE_128,
AES_MODE_256
} AES_MODE;
void AES_set_key(AES_CTX *ctx, const uint8_t *key,
const uint8_t *iv, AES_MODE mode);
void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
uint8_t *out, int length);
void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
void AES_convert_key(AES_CTX *ctx);
/**************************************************************************
* RC4 declarations
**************************************************************************/
typedef struct
{
int x, y, m[256];
} RC4_CTX;
void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
/**************************************************************************
* SHA1 declarations
**************************************************************************/
#define SHA1_SIZE 20
/*
* This structure will hold context information for the SHA-1
* hashing operation
*/
typedef struct
{
uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
uint16_t Message_Block_Index; /* Index into message block array */
uint8_t Message_Block[64]; /* 512-bit message blocks */
} SHA1_CTX;
void SHA1Init(SHA1_CTX *);
void SHA1Update(SHA1_CTX *, const uint8_t * msg, int len);
void SHA1Final(SHA1_CTX *, uint8_t *digest);
/**************************************************************************
* MD5 declarations
**************************************************************************/
/* MD5 context. */
#define MD5_SIZE 16
typedef struct
{
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
uint8_t buffer[64]; /* input buffer */
} MD5_CTX;
EXP_FUNC void STDCALL MD5Init(MD5_CTX *);
EXP_FUNC void STDCALL MD5Update(MD5_CTX *, const uint8_t *msg, int len);
EXP_FUNC void STDCALL MD5Final(MD5_CTX *, uint8_t *digest);
/**************************************************************************
* HMAC declarations
**************************************************************************/
void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
/**************************************************************************
* RNG declarations
**************************************************************************/
EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
EXP_FUNC void STDCALL RNG_terminate(void);
EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
/**************************************************************************
* RSA declarations
**************************************************************************/
typedef struct
{
bigint *m; /* modulus */
bigint *e; /* public exponent */
bigint *d; /* private exponent */
#ifdef CONFIG_BIGINT_CRT
bigint *p; /* p as in m = pq */
bigint *q; /* q as in m = pq */
bigint *dP; /* d mod (p-1) */
bigint *dQ; /* d mod (q-1) */
bigint *qInv; /* q^-1 mod p */
#endif
int num_octets;
BI_CTX *bi_ctx;
} RSA_CTX;
void RSA_priv_key_new(RSA_CTX **rsa_ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len,
const uint8_t *priv_exp, int priv_len
#ifdef CONFIG_BIGINT_CRT
, const uint8_t *p, int p_len,
const uint8_t *q, int q_len,
const uint8_t *dP, int dP_len,
const uint8_t *dQ, int dQ_len,
const uint8_t *qInv, int qInv_len
#endif
);
void RSA_pub_key_new(RSA_CTX **rsa_ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len);
void RSA_free(RSA_CTX *ctx);
int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
int is_decryption);
bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
#ifdef CONFIG_SSL_CERT_VERIFICATION
bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
bigint *modulus, bigint *pub_exp);
bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
uint8_t *out_data, int is_signing);
void RSA_print(const RSA_CTX *ctx);
#endif
/**************************************************************************
* ASN1 declarations
**************************************************************************/
#define X509_OK 0
#define X509_NOT_OK -1
#define X509_VFY_ERROR_NO_TRUSTED_CERT -2
#define X509_VFY_ERROR_BAD_SIGNATURE -3
#define X509_VFY_ERROR_NOT_YET_VALID -4
#define X509_VFY_ERROR_EXPIRED -5
#define X509_VFY_ERROR_SELF_SIGNED -6
#define X509_VFY_ERROR_INVALID_CHAIN -7
#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8
#define X509_INVALID_PRIV_KEY -9
/*
* The Distinguished Name
*/
#define X509_NUM_DN_TYPES 3
#define X509_COMMON_NAME 0
#define X509_ORGANIZATION 1
#define X509_ORGANIZATIONAL_TYPE 2
#define ASN1_INTEGER 0x02
#define ASN1_BIT_STRING 0x03
#define ASN1_OCTET_STRING 0x04
#define ASN1_NULL 0x05
#define ASN1_OID 0x06
#define ASN1_PRINTABLE_STR 0x13
#define ASN1_TELETEX_STR 0x14
#define ASN1_IA5_STR 0x16
#define ASN1_UTC_TIME 0x17
#define ASN1_SEQUENCE 0x30
#define ASN1_SET 0x31
#define ASN1_IMPLICIT_TAG 0x80
#define ASN1_EXPLICIT_TAG 0xa0
#define SALT_SIZE 8
struct _x509_ctx
{
char *ca_cert_dn[X509_NUM_DN_TYPES];
char *cert_dn[X509_NUM_DN_TYPES];
#if defined(_WIN32_WCE)
long not_before;
long not_after;
#else
time_t not_before;
time_t not_after;
#endif
uint8_t *signature;
uint16_t sig_len;
uint8_t sig_type;
RSA_CTX *rsa_ctx;
bigint *digest;
struct _x509_ctx *next;
};
typedef struct _x509_ctx X509_CTX;
#ifdef CONFIG_SSL_CERT_VERIFICATION
typedef struct
{
X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS];
} CA_CERT_CTX;
#endif
int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object);
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
void x509_free(X509_CTX *x509_ctx);
#ifdef CONFIG_SSL_CERT_VERIFICATION
int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
const uint8_t *x509_get_signature(const uint8_t *asn1_signature, int *len);
#endif
#ifdef CONFIG_SSL_FULL_MODE
void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
void x509_display_error(int error);
#endif
/**************************************************************************
* MISC declarations
**************************************************************************/
extern const char * const unsupported_str;
typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int);
typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
int get_file(const char *filename, uint8_t **buf);
#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)
EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
#else
#define print_blob(...)
#endif
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen);
#ifdef __cplusplus
}
#endif
#endif

345
ssl/crypto_misc.c Normal file
View File

@ -0,0 +1,345 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Some misc. routines to help things out
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "crypto.h"
#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
#include "wincrypt.h"
#endif
#ifndef WIN32
static int rng_fd = -1;
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
static HCRYPTPROV gCryptProv;
#endif
#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
static uint64_t rng_num;
#endif
static int rng_ref_count;
const char * const unsupported_str = "Error: feature not supported\n";
#ifndef CONFIG_SSL_SKELETON_MODE
/**
* Retrieve a file and put it into memory
* @return The size of the file, or -1 on failure.
*/
int get_file(const char *filename, uint8_t **buf)
{
int total_bytes = 0;
int bytes_read = 0;
int filesize;
FILE *stream = fopen(filename, "rb");
if (stream == NULL)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("file '%s' does not exist\n", filename); TTY_FLUSH();
#endif
return -1;
}
/* Win CE doesn't support stat() */
fseek(stream, 0, SEEK_END);
filesize = ftell(stream);
*buf = (uint8_t *)malloc(filesize);
fseek(stream, 0, SEEK_SET);
do
{
bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream);
total_bytes += bytes_read;
} while (total_bytes < filesize && bytes_read > 0);
fclose(stream);
return filesize;
}
#endif
/**
* Initialise the Random Number Generator engine.
* - On Win32 use the platform SDK's crypto engine.
* - On Linux use /dev/urandom
* - If none of these work then use a custom RNG.
*/
EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size)
{
if (rng_ref_count == 0)
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
rng_fd = ax_open("/dev/urandom", O_RDONLY);
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
if (!CryptAcquireContext(&gCryptProv,
NULL, NULL, PROV_RSA_FULL, 0))
{
if (GetLastError() == NTE_BAD_KEYSET &&
!CryptAcquireContext(&gCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("CryptoLib: %x\n", unsupported_str, GetLastError());
exit(1);
}
}
#else
/* help seed with the user's private key - this is a number that
should be hard to find, due to the fact that it relies on knowing
the private key */
int i;
for (i = 0; i < size/(int)sizeof(uint64_t); i++)
rng_num ^= *((uint64_t *)&seed_buf[i*sizeof(uint64_t)]);
srand((long)seed_buf); /* use the stack ptr as another rnd seed */
#endif
}
rng_ref_count++;
}
/**
* Terminate the RNG engine.
*/
EXP_FUNC void STDCALL RNG_terminate(void)
{
if (--rng_ref_count == 0)
{
#ifndef WIN32
close(rng_fd);
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
CryptReleaseContext(gCryptProv, 0);
#endif
}
}
/**
* Set a series of bytes with a random number. Individual bytes can be 0
*/
EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
/* use the Linux default */
read(rng_fd, rand_data, num_rand_bytes); /* read from /dev/urandom */
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
/* use Microsoft Crypto Libraries */
CryptGenRandom(gCryptProv, num_rand_bytes, rand_data);
#else /* nothing else to use, so use a custom RNG */
/* The method we use when we've got nothing better. Use RC4, time
and a couple of random seeds to generate a random sequence */
RC4_CTX rng_ctx;
struct timeval tv;
uint64_t big_num1, big_num2;
gettimeofday(&tv, NULL); /* yes I know we shouldn't do this */
/* all numbers by themselves are pretty simple, but combined should
* be a challenge */
big_num1 = (uint64_t)tv.tv_sec*(tv.tv_usec+1);
big_num2 = (uint64_t)rand()*big_num1;
big_num1 ^= rng_num;
memcpy(rand_data, &big_num1, sizeof(uint64_t));
if (num_rand_bytes > sizeof(uint64_t))
memcpy(&rand_data[8], &big_num2, sizeof(uint64_t));
if (num_rand_bytes > 16)
{
/* clear rest of data */
memset(&rand_data[16], 0, num_rand_bytes-16);
}
RC4_setup(&rng_ctx, rand_data, 16); /* use as a key */
RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
/* use last 8 bytes for next time */
memcpy(&rng_num, &rand_data[num_rand_bytes-8], sizeof(uint64_t));
#endif
}
/**
* Set a series of bytes with a random number. Individual bytes are not zero.
*/
void get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
{
int i;
get_random(num_rand_bytes, rand_data);
for (i = 0; i < num_rand_bytes; i++)
{
while (rand_data[i] == 0) /* can't be 0 */
rand_data[i] = (uint8_t)(rand());
}
}
/**
* Some useful diagnostic routines
*/
#if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
int hex_finish;
int hex_index;
static void print_hex_init(int finish)
{
hex_finish = finish;
hex_index = 0;
}
static void print_hex(uint8_t hex)
{
static int column;
if (hex_index == 0)
{
column = 0;
}
printf("%02x ", hex);
if (++column == 8)
{
printf(": ");
}
else if (column >= 16)
{
printf("\n");
column = 0;
}
if (++hex_index >= hex_finish && column > 0)
{
printf("\n");
}
}
/**
* Spit out a blob of data for diagnostics. The data is is a nice column format
* for easy reading.
*
* @param format [in] The string (with possible embedded format characters)
* @param size [in] The number of numbers to print
* @param data [in] The start of data to use
* @param ... [in] Any additional arguments
*/
EXP_FUNC void STDCALL print_blob(const char *format,
const uint8_t *data, int size, ...)
{
int i;
char tmp[80];
va_list(ap);
va_start(ap, size);
sprintf(tmp, "%s\n", format);
vprintf(tmp, ap);
print_hex_init(size);
for (i = 0; i < size; i++)
{
print_hex(data[i]);
}
va_end(ap);
TTY_FLUSH();
}
#elif defined(WIN32)
/* VC6.0 doesn't handle variadic macros */
EXP_FUNC void STDCALL print_blob(const char *format, const unsigned char *data,
int size, ...) {}
#endif
#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
/* base64 to binary lookup table */
static const uint8_t map[128] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255
};
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen)
{
int g, t, x, y, z;
uint8_t c;
int ret = -1;
g = 3;
for (x = y = z = t = 0; x < len; x++)
{
if ((c = map[in[x]&0x7F]) == 0xff)
continue;
if (c == 254) /* this is the end... */
{
c = 0;
if (--g < 0)
goto error;
}
else if (g != 3) /* only allow = at end */
goto error;
t = (t<<6) | c;
if (++y == 4)
{
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1)
out[z++] = (uint8_t)((t>>8)&255);
if (g > 2)
out[z++] = (uint8_t)(t&255);
y = t = 0;
}
}
if (y != 0)
goto error;
if (outlen)
*outlen = z;
ret = 0;
error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret < 0)
printf("Error: Invalid base64\n"); TTY_FLUSH();
#endif
TTY_FLUSH();
return ret;
}
#endif

88
ssl/hmac.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* HMAC implementation - This code was originally taken from RFC2104
*/
#include <string.h>
#include "crypto.h"
/**
* Perform HMAC-MD5
*/
void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
MD5_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
MD5Init(&context);
MD5Update(&context, k_ipad, 64);
MD5Update(&context, msg, length);
MD5Final(&context, digest);
MD5Init(&context);
MD5Update(&context, k_opad, 64);
MD5Update(&context, digest, MD5_SIZE);
MD5Final(&context, digest);
}
/**
* Perform HMAC-SHA1
*/
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
SHA1_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
SHA1Init(&context);
SHA1Update(&context, k_ipad, 64);
SHA1Update(&context, msg, length);
SHA1Final(&context, digest);
SHA1Init(&context);
SHA1Update(&context, k_opad, 64);
SHA1Update(&context, digest, SHA1_SIZE);
SHA1Final(&context, digest);
}

375
ssl/loader.c Normal file
View File

@ -0,0 +1,375 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 library 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 Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Load certificates/keys into memory. These can be in many different formats.
* PEM support and other formats can be processed here.
*
* The PEM private keys may be optionally encrypted with AES128 or AES256.
* The encrypted PEM keys were generated with something like:
*
* openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ssl.h"
static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
SSLObjLoader *ssl_obj, const char *password);
#ifdef CONFIG_SSL_HAS_PEM
static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj,
const char *password);
#endif
/*
* Load a file into memory that is in binary DER (or ascii PEM) format.
*/
EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type,
const char *filename, const char *password)
{
#ifndef CONFIG_SSL_SKELETON_MODE
static const char * const begin = "-----BEGIN";
int ret = SSL_OK;
SSLObjLoader *ssl_obj = NULL;
if (filename == NULL)
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
ssl_obj->len = get_file(filename, &ssl_obj->buf);
if (ssl_obj->len <= 0)
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
/* is the file a PEM file? */
if (strncmp((char *)ssl_obj->buf, begin, strlen(begin)) == 0)
{
#ifdef CONFIG_SSL_HAS_PEM
ret = ssl_obj_PEM_load(ssl_ctx, ssl_obj, password);
#else
printf(unsupported_str);
ret = SSL_ERROR_NOT_SUPPORTED;
#endif
}
else
ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
error:
ssl_obj_free(ssl_obj);
return ret;
#else
printf(unsupported_str);
return SSL_ERROR_NOT_SUPPORTED;
#endif /* CONFIG_SSL_SKELETON_MODE */
}
/*
* Transfer binary data into the object loader.
*/
EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type,
const uint8_t *data, int len, const char *password)
{
int ret;
SSLObjLoader *ssl_obj;
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
ssl_obj->buf = (uint8_t *)malloc(len);
memcpy(ssl_obj->buf, data, len);
ssl_obj->len = len;
ret = do_obj(ssl_ctx, mem_type, ssl_obj, password);
ssl_obj_free(ssl_obj);
return ret;
}
/*
* Actually work out what we are doing
*/
static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
SSLObjLoader *ssl_obj, const char *password)
{
int ret = SSL_OK;
switch (obj_type)
{
case SSL_OBJ_RSA_KEY:
ret = add_private_key(ssl_ctx, ssl_obj);
break;
case SSL_OBJ_X509_CERT:
ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
break;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case SSL_OBJ_X509_CACERT:
ret = add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
break;
#endif
#ifdef CONFIG_SSL_USE_PKCS12
case SSL_OBJ_PKCS8:
ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
break;
case SSL_OBJ_PKCS12:
ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
break;
#endif
default:
printf(unsupported_str);
ret = SSL_ERROR_NOT_SUPPORTED;
break;
}
return ret;
}
/*
* Clean up our mess.
*/
void ssl_obj_free(SSLObjLoader *ssl_obj)
{
if (ssl_obj)
{
free(ssl_obj->buf);
free(ssl_obj);
}
}
/*
* Support for PEM encoded keys/certificates.
*/
#ifdef CONFIG_SSL_HAS_PEM
#define NUM_PEM_TYPES 3
#define IV_SIZE 16
#define IS_RSA_PRIVATE_KEY 0
#define IS_ENCRYPTED_PRIVATE_KEY 1
#define IS_CERTIFICATE 2
static const char * const begins[NUM_PEM_TYPES] =
{
"-----BEGIN RSA PRIVATE KEY-----",
"-----BEGIN ENCRYPTED PRIVATE KEY-----",
"-----BEGIN CERTIFICATE-----",
};
static const char * const ends[NUM_PEM_TYPES] =
{
"-----END RSA PRIVATE KEY-----",
"-----END ENCRYPTED PRIVATE KEY-----",
"-----END CERTIFICATE-----",
};
static const char * const aes_str[2] =
{
"DEK-Info: AES-128-CBC,",
"DEK-Info: AES-256-CBC,"
};
/**
* Take a base64 blob of data and decrypt it (using AES) into its
* proper ASN.1 form.
*/
static int pem_decrypt(const char *where, const char *end,
const char *password, SSLObjLoader *ssl_obj)
{
int ret = -1;
int is_aes_256 = 0;
char *start = NULL;
uint8_t iv[IV_SIZE];
int i, pem_size;
MD5_CTX md5_ctx;
AES_CTX aes_ctx;
uint8_t key[32]; /* AES256 size */
if (password == NULL)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: need a password for this PEM file\n");
#endif
goto error;
}
if ((start = strstr((const char *)where, aes_str[0]))) /* AES128? */
{
start += strlen(aes_str[0]);
}
else if ((start = strstr((const char *)where, aes_str[1]))) /* AES256? */
{
is_aes_256 = 1;
start += strlen(aes_str[1]);
}
else
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Unsupported password cipher\n");
#endif
goto error;
}
/* convert from hex to binary - assumes uppercase hex */
for (i = 0; i < IV_SIZE; i++)
{
char c = *start++ - '0';
iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
c = *start++ - '0';
iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
}
while (*start == '\r' || *start == '\n')
start++;
/* turn base64 into binary */
pem_size = (int)(end-start);
if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
goto error;
/* work out the key */
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, (const uint8_t *)password, strlen(password));
MD5Update(&md5_ctx, iv, SALT_SIZE);
MD5Final(&md5_ctx, key);
if (is_aes_256)
{
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, key, MD5_SIZE);
MD5Update(&md5_ctx, (const uint8_t *)password, strlen(password));
MD5Update(&md5_ctx, iv, SALT_SIZE);
MD5Final(&md5_ctx, &key[MD5_SIZE]);
}
/* decrypt using the key/iv */
AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
AES_convert_key(&aes_ctx);
AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
ret = 0;
error:
return ret;
}
/**
* Take a base64 blob of data and turn it into its proper ASN.1 form.
*/
static int new_pem_obj(SSL_CTX *ssl_ctx, char *where,
int remain, const char *password)
{
int ret = SSL_OK;
SSLObjLoader *ssl_obj = NULL;
int i, pem_size, obj_type;
char *start = NULL, *end = NULL;
for (i = 0; i < NUM_PEM_TYPES; i++)
{
if ((start = strstr(where, begins[i])) &&
(end = strstr(where, ends[i])))
{
remain -= (int)(end-start);
start += strlen(begins[i]);
pem_size = (int)(end-start);
ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
/* 4/3 bigger than what we need but so what */
ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
if (i == IS_RSA_PRIVATE_KEY &&
strstr(start, "Proc-Type:") &&
strstr(start, "4,ENCRYPTED"))
{
/* check for encrypted PEM file */
if (pem_decrypt(start, end, password, ssl_obj) < 0)
goto error;
}
else if (base64_decode(start, pem_size,
ssl_obj->buf, &ssl_obj->len) != 0)
goto error;
switch (i)
{
case IS_RSA_PRIVATE_KEY:
obj_type = SSL_OBJ_RSA_KEY;
break;
case IS_ENCRYPTED_PRIVATE_KEY:
obj_type = SSL_OBJ_PKCS8;
break;
case IS_CERTIFICATE:
obj_type = SSL_OBJ_X509_CERT;
break;
default:
goto error;
}
/* In a format we can now understand - so process it */
if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
goto error;
end += strlen(ends[i]);
remain -= strlen(ends[i]);
while (remain > 0 && (*end == '\r' || *end == '\n'))
{
end++;
remain--;
}
break;
}
}
if (i == NUM_PEM_TYPES)
goto error;
/* more PEM stuff to process? */
if (remain)
ret = new_pem_obj(ssl_ctx, end, remain, password);
error:
ssl_obj_free(ssl_obj);
return ret;
}
/*
* Load a file into memory that is in ASCII PEM format.
*/
static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj,
const char *password)
{
char *start;
/* add a null terminator */
ssl_obj->len++;
ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
ssl_obj->buf[ssl_obj->len-1] = 0;
start = (char *)ssl_obj->buf;
return new_pem_obj(ssl_ctx, start, ssl_obj->len, password);
}
#endif /* CONFIG_SSL_HAS_PEM */

Some files were not shown because too many files have changed in this diff Show More