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:
parent
974cf12924
commit
73dfbb7568
162
Makefile
Normal file
162
Makefile
Normal 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
3
README
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
See www/index.html for the README, CHANGELOG, LICENSE and other notes.
|
||||
|
89
bindings/Config.in
Normal file
89
bindings/Config.in
Normal 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
63
bindings/Makefile
Normal 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
43
bindings/README
Normal 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
23
bindings/csharp/Makefile
Normal 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
477
bindings/csharp/axTLS.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
/** @} */
|
328
bindings/generate_SWIG_interface.pl
Executable file
328
bindings/generate_SWIG_interface.pl
Executable 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
307
bindings/generate_interface.pl
Executable 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
93
bindings/java/Makefile
Normal 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
125
bindings/java/SSL.java
Normal 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
219
bindings/java/SSLCTX.java
Normal 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);
|
||||
}
|
||||
}
|
66
bindings/java/SSLClient.java
Normal file
66
bindings/java/SSLClient.java
Normal 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));
|
||||
}
|
||||
}
|
49
bindings/java/SSLReadHolder.java
Normal file
49
bindings/java/SSLReadHolder.java
Normal 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;
|
||||
}
|
60
bindings/java/SSLServer.java
Normal file
60
bindings/java/SSLServer.java
Normal 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
104
bindings/java/SSLUtil.java
Normal 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
81
bindings/perl/Makefile
Normal 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
23
bindings/vbnet/Makefile
Normal 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
179
bindings/vbnet/axTLSvb.vb
Normal 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
11
config/.config.tmp
Normal 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
120
config/Config.in
Normal 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
247
config/JMeter.jmx
Executable 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
220
config/Rules.mak
Normal 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
149
config/axhttpd.aip
Executable 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 <product name>." 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="<ui.ail>"/>
|
||||
<ROW Path="<ui_en.ail>"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
|
||||
<ROW Fragment="FolderDlg.aip" Path="<FolderDlg.aip>"/>
|
||||
<ROW Fragment="StaticUIStrings.aip" Path="<StaticUIStrings.aip>"/>
|
||||
<ROW Fragment="UI.aip" Path="<UI.aip>"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
|
||||
<ROW Name="default_banner.bmp" SourcePath="<default-banner.bmp>"/>
|
||||
<ROW Name="default_dialog.bmp" SourcePath="<default-dialog.bmp>"/>
|
||||
<ROW Name="launcher.dll" SourcePath="<launcher.dll>"/>
|
||||
</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 <> 5)" Sequence="210"/>
|
||||
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=""" Sequence="740"/>
|
||||
<ROW Action="AI_STORE_LOCATION" Condition="Not Installed" Sequence="1545"/>
|
||||
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE="No" AND (Not Installed)" Sequence="1300"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
|
||||
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=""" 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
BIN
config/axtls.RES
Normal file
Binary file not shown.
32
config/axtls.rc
Normal file
32
config/axtls.rc
Normal 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
106
config/config.h
Normal 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
103
config/linuxconfig
Normal 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
121
config/makefile.conf
Normal 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*
|
||||
|
53
config/makefile.dotnet.conf
Normal file
53
config/makefile.dotnet.conf
Normal 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
56
config/makefile.java.conf
Normal 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
19
config/makefile.post
Normal 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
|
255
config/scripts/config/Kconfig-language.txt
Normal file
255
config/scripts/config/Kconfig-language.txt
Normal 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.
|
121
config/scripts/config/Makefile
Normal file
121
config/scripts/config/Makefile
Normal 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
|
||||
|
583
config/scripts/config/conf.c
Normal file
583
config/scripts/config/conf.c
Normal 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;
|
||||
}
|
458
config/scripts/config/confdata.c
Normal file
458
config/scripts/config/confdata.c
Normal 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
1099
config/scripts/config/expr.c
Normal file
File diff suppressed because it is too large
Load Diff
195
config/scripts/config/expr.h
Normal file
195
config/scripts/config/expr.h
Normal 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 */
|
3688
config/scripts/config/lex.zconf.c_shipped
Normal file
3688
config/scripts/config/lex.zconf.c_shipped
Normal file
File diff suppressed because it is too large
Load Diff
123
config/scripts/config/lkc.h
Normal file
123
config/scripts/config/lkc.h
Normal 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 */
|
40
config/scripts/config/lkc_proto.h
Normal file
40
config/scripts/config/lkc_proto.h
Normal 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));
|
4
config/scripts/config/lxdialog/BIG.FAT.WARNING
Normal file
4
config/scripts/config/lxdialog/BIG.FAT.WARNING
Normal 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.
|
372
config/scripts/config/lxdialog/checklist.c
Normal file
372
config/scripts/config/lxdialog/checklist.c
Normal 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 */
|
||||
}
|
161
config/scripts/config/lxdialog/colors.h
Normal file
161
config/scripts/config/lxdialog/colors.h
Normal 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];
|
199
config/scripts/config/lxdialog/dialog.h
Normal file
199
config/scripts/config/lxdialog/dialog.h
Normal 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
|
240
config/scripts/config/lxdialog/inputbox.c
Normal file
240
config/scripts/config/lxdialog/inputbox.c
Normal 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 */
|
||||
}
|
438
config/scripts/config/lxdialog/menubox.c
Normal file
438
config/scripts/config/lxdialog/menubox.c
Normal 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 */
|
||||
}
|
85
config/scripts/config/lxdialog/msgbox.c
Normal file
85
config/scripts/config/lxdialog/msgbox.c
Normal 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;
|
||||
}
|
556
config/scripts/config/lxdialog/textbox.c
Normal file
556
config/scripts/config/lxdialog/textbox.c
Normal 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);
|
||||
}
|
375
config/scripts/config/lxdialog/util.c
Normal file
375
config/scripts/config/lxdialog/util.c
Normal 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;
|
||||
}
|
118
config/scripts/config/lxdialog/yesno.c
Normal file
118
config/scripts/config/lxdialog/yesno.c
Normal 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 */
|
||||
}
|
977
config/scripts/config/mconf.c
Normal file
977
config/scripts/config/mconf.c
Normal 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;
|
||||
}
|
390
config/scripts/config/menu.c
Normal file
390
config/scripts/config/menu.c
Normal 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 = ¤t_entry->list;
|
||||
}
|
||||
|
||||
void menu_end_menu(void)
|
||||
{
|
||||
last_entry_ptr = ¤t_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
67
config/scripts/config/mkconfigs
Executable 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 */"
|
809
config/scripts/config/symbol.c
Normal file
809
config/scripts/config/symbol.c
Normal 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";
|
||||
}
|
109
config/scripts/config/util.c
Normal file
109
config/scripts/config/util.c
Normal 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;
|
||||
}
|
||||
|
366
config/scripts/config/zconf.l
Normal file
366
config/scripts/config/zconf.l
Normal 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>";
|
||||
}
|
2130
config/scripts/config/zconf.tab.c_shipped
Normal file
2130
config/scripts/config/zconf.tab.c_shipped
Normal file
File diff suppressed because it is too large
Load Diff
125
config/scripts/config/zconf.tab.h_shipped
Normal file
125
config/scripts/config/zconf.tab.h_shipped
Normal 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 */
|
||||
|
690
config/scripts/config/zconf.y
Normal file
690
config/scripts/config/zconf.y
Normal 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
116
config/win32config
Normal 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
27
docsrc/Makefile
Normal 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
1237
docsrc/axTLS.dox
Normal file
File diff suppressed because it is too large
Load Diff
3
docsrc/doco_footer.html
Normal file
3
docsrc/doco_footer.html
Normal 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
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
BIN
docsrc/images/tsbasbw.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
138
httpd/Config.in
Normal file
138
httpd/Config.in
Normal 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
104
httpd/Makefile
Normal 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
133
httpd/axhttp.h
Normal 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
567
httpd/axhttpd.c
Normal 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
124
httpd/htpasswd.c
Normal 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
194
httpd/mime_types.c
Normal 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
1034
httpd/proc.c
Normal file
File diff suppressed because it is too large
Load Diff
107
httpd/tdate_parse.c
Normal file
107
httpd/tdate_parse.c
Normal 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
56
samples/Config.in
Normal 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
46
samples/Makefile
Normal 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
66
samples/c/Makefile
Normal 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
865
samples/c/axssl.c
Normal 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
36
samples/csharp/Makefile
Normal 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
743
samples/csharp/axssl.cs
Normal 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
39
samples/java/Makefile
Normal 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
746
samples/java/axssl.java
Normal 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
1
samples/java/manifest.mf
Normal file
@ -0,0 +1 @@
|
||||
Main-Class: axssl
|
31
samples/perl/Makefile
Normal file
31
samples/perl/Makefile
Normal 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
629
samples/perl/axssl.pl
Executable 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
36
samples/vbnet/Makefile
Normal 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
687
samples/vbnet/axssl.vb
Normal 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
132
ssl/BigIntConfig.in
Normal 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
274
ssl/Config.in
Normal 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
101
ssl/Makefile
Normal 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
444
ssl/aes.c
Normal 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
864
ssl/asn1.c
Normal 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
1506
ssl/bigint.c
Normal file
File diff suppressed because it is too large
Load Diff
93
ssl/bigint.h
Normal file
93
ssl/bigint.h
Normal 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
105
ssl/bigint_impl.h
Normal 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
43
ssl/cert.h
Normal 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
285
ssl/crypto.h
Normal 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
345
ssl/crypto_misc.c
Normal 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
88
ssl/hmac.c
Normal 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
375
ssl/loader.c
Normal 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
Loading…
x
Reference in New Issue
Block a user