the original qca-1.0 sources with the TQt layer added. This resolves bug report 817.pull/1/head
commit
c663e43e71
@ -0,0 +1,12 @@
|
||||
Installing QCA
|
||||
--------------
|
||||
|
||||
Installation should be straightforward:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
NOTE: You may also need to run '/sbin/ldconfig' or a similar tool to
|
||||
get the new library files recognized by the system. If you are
|
||||
using Linux, just run it for good measure.
|
@ -0,0 +1,29 @@
|
||||
Qt Cryptographic Architecture
|
||||
-----------------------------
|
||||
Version: API v1.0, Plugin v1
|
||||
Author: Justin Karneges <justin@affinix.com>
|
||||
Date: September 10th 2003
|
||||
|
||||
This library provides an easy API for the following features:
|
||||
|
||||
SSL/TLS
|
||||
X509
|
||||
SASL
|
||||
RSA
|
||||
Hashing (SHA1, MD5)
|
||||
Ciphers (BlowFish, 3DES, AES)
|
||||
|
||||
Functionality is supplied via plugins. This is useful for avoiding
|
||||
dependence on a particular crypto library and makes upgrading easier,
|
||||
as there is no need to recompile your application when adding or
|
||||
upgrading a crypto plugin. Also, by pushing crypto functionality into
|
||||
plugins, your application is free of legal issues, such as export
|
||||
regulation.
|
||||
|
||||
And of course, you get a very simple crypto API for Qt, where you can
|
||||
do things like:
|
||||
|
||||
TQString hash = QCA::SHA1::hashToString(blockOfData);
|
||||
|
||||
Have fun!
|
||||
|
@ -0,0 +1,6 @@
|
||||
* plugins: thread safety ?
|
||||
|
||||
* dsa
|
||||
* diffie-hellman
|
||||
* entropy
|
||||
|
@ -0,0 +1,492 @@
|
||||
#!/bin/sh
|
||||
|
||||
show_usage() {
|
||||
cat <<EOT
|
||||
Usage: ./configure [OPTION]...
|
||||
|
||||
This script creates necessary configuration files to build/install.
|
||||
|
||||
Main options:
|
||||
--prefix=[path] Base path for build/install. Default: /usr/local
|
||||
--qtdir=[path] Directory where Qt is installed.
|
||||
--help This help text.
|
||||
|
||||
EOT
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--prefix=*)
|
||||
PREFIX=`expr "${1}" : "--prefix=\(.*\)"`
|
||||
shift
|
||||
;;
|
||||
|
||||
--qtdir=*)
|
||||
QTDIR=`expr "${1}" : "--qtdir=\(.*\)"`
|
||||
shift
|
||||
;;
|
||||
|
||||
--debug)
|
||||
QC_DEBUG="Y"
|
||||
shift
|
||||
;;
|
||||
--help) show_usage; exit ;;
|
||||
*) show_usage; exit ;;
|
||||
esac
|
||||
done
|
||||
|
||||
PREFIX=${PREFIX:-/usr/local}
|
||||
|
||||
echo "Configuring TQt Cryptographic Architecture (QCA) ..."
|
||||
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
echo
|
||||
echo PREFIX=$PREFIX
|
||||
echo QTDIR=$QTDIR
|
||||
echo
|
||||
fi
|
||||
|
||||
printf "Verifying TQt 3.x Multithreaded (MT) build environment ... "
|
||||
|
||||
if [ -z "$QTDIR" ]; then
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
echo \$QTDIR not set... trying to find Qt manually
|
||||
fi
|
||||
for p in /usr/lib/tqt /usr/share/tqt /usr/share/tqt3 /usr/local/lib/tqt /usr/local/share/tqt /usr/lib/tqt3 /usr/local/lib/tqt3 /usr/lib/qt /usr/share/qt /usr/share/qt3 /usr/local/lib/qt /usr/local/share/qt /usr/lib/qt3 /usr/local/lib/qt3 /usr/X11R6/share/qt /usr/qt/3 ; do
|
||||
if [ -d "$p/mkspecs" ]; then
|
||||
QTDIR=$p
|
||||
break;
|
||||
fi;
|
||||
done
|
||||
if [ -z "$QTDIR" ]; then
|
||||
echo fail
|
||||
echo
|
||||
echo Unable to find Qt 'mkspecs'. Please set QTDIR
|
||||
echo manually. Perhaps you need to install Qt 3
|
||||
echo development utilities. You may download them either
|
||||
echo from the vendor of your operating system or from
|
||||
echo www.trolltech.com
|
||||
echo
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$QTDIR/bin/qmake" ]; then
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
echo Warning: qmake not in \$QTDIR/bin/qmake
|
||||
echo trying to find it in \$PATH
|
||||
fi
|
||||
qm=`type -p qmake`
|
||||
if [ -x "$qm" ]; then
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
echo qmake found in $qm
|
||||
fi
|
||||
else
|
||||
echo fail
|
||||
echo
|
||||
echo Sorry, you seem to have a very unusual setup,
|
||||
echo or I missdetected \$QTDIR=$QTDIR
|
||||
echo
|
||||
echo Please set \$QTDIR manually and make sure that
|
||||
echo \$QTDIR/bin/qmake exists.
|
||||
echo
|
||||
exit 1;
|
||||
fi
|
||||
else
|
||||
qm=$QTDIR/bin/qmake
|
||||
fi
|
||||
|
||||
gen_files() {
|
||||
cat >$1/modules.cpp <<EOT
|
||||
|
||||
EOT
|
||||
cat >$1/modules_new.cpp <<EOT
|
||||
|
||||
EOT
|
||||
cat >$1/conf.cpp <<EOT
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<tqstring.h>
|
||||
#include<tqdict.h>
|
||||
#include<tqptrlist.h>
|
||||
#include<tqfileinfo.h>
|
||||
#include<tqfile.h>
|
||||
#include<tqdir.h>
|
||||
#include<tqstringlist.h>
|
||||
|
||||
class Conf;
|
||||
|
||||
class ConfObj
|
||||
{
|
||||
public:
|
||||
ConfObj(Conf *c);
|
||||
virtual ~ConfObj();
|
||||
|
||||
virtual TQString name() const=0;
|
||||
virtual TQString shortname() const=0;
|
||||
virtual bool exec()=0;
|
||||
|
||||
Conf *conf;
|
||||
bool required;
|
||||
bool disabled;
|
||||
};
|
||||
|
||||
typedef TQPtrList<ConfObj> ConfObjList;
|
||||
typedef TQPtrListIterator<ConfObj> ConfObjListIt;
|
||||
|
||||
class Conf
|
||||
{
|
||||
public:
|
||||
Conf() : vars(17)
|
||||
{
|
||||
list.setAutoDelete(true);
|
||||
vars.setAutoDelete(true);
|
||||
|
||||
vars.insert("QMAKE_INCDIR_X11", new TQString(X11_INC));
|
||||
vars.insert("QMAKE_LIBDIR_X11", new TQString(X11_LIBDIR));
|
||||
vars.insert("QMAKE_LIBS_X11", new TQString(X11_LIB));
|
||||
vars.insert("QMAKE_CC", new TQString(CC));
|
||||
}
|
||||
|
||||
~Conf()
|
||||
{
|
||||
}
|
||||
|
||||
void added(ConfObj *o)
|
||||
{
|
||||
list.append(o);
|
||||
}
|
||||
|
||||
TQString getenv(const TQString &var)
|
||||
{
|
||||
char *p = ::getenv(var.latin1());
|
||||
if(!p)
|
||||
return TQString::null;
|
||||
return TQString(p);
|
||||
}
|
||||
|
||||
bool exec()
|
||||
{
|
||||
ConfObjListIt it(list);
|
||||
for(ConfObj *o; (o = it.current()); ++it) {
|
||||
// if this was a disabled-by-default option, check if it was enabled
|
||||
if(o->disabled) {
|
||||
TQString v = TQString("QC_ENABLE_") + o->shortname();
|
||||
if(getenv(v) != "Y")
|
||||
continue;
|
||||
}
|
||||
// and the opposite?
|
||||
else {
|
||||
TQString v = TQString("QC_DISABLE_") + o->shortname();
|
||||
if(getenv(v) == "Y")
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("Checking for %s ...", o->name().latin1());
|
||||
fflush(stdout);
|
||||
bool ok = o->exec();
|
||||
if(ok)
|
||||
printf(" yes\n");
|
||||
else
|
||||
printf(" no\n");
|
||||
if(!ok && o->required) {
|
||||
printf("\nError: need %s!\n", o->name().latin1());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const TQString & qvar(const TQString &s)
|
||||
{
|
||||
TQString *p = vars.find(s);
|
||||
if(p)
|
||||
return *p;
|
||||
else
|
||||
return blank;
|
||||
}
|
||||
|
||||
TQString expandIncludes(const TQString &inc)
|
||||
{
|
||||
return TQString("-I") + inc;
|
||||
}
|
||||
|
||||
TQString expandLibs(const TQString &lib)
|
||||
{
|
||||
return TQString("-L") + lib;
|
||||
}
|
||||
|
||||
int doCommand(const TQString &s)
|
||||
{
|
||||
//printf("[%s]\n", s.latin1());
|
||||
int r = system((s + " 1>/dev/null 2>/dev/null").latin1());
|
||||
//printf("returned: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool doCompileAndLink(const TQString &filedata, const TQString &flags, int *retcode=0)
|
||||
{
|
||||
TQDir dir(".");
|
||||
TQString fname = "atest.c";
|
||||
TQString out = "atest";
|
||||
TQFile f(fname);
|
||||
TQCString cs = filedata.latin1();
|
||||
if(!f.open(IO_WriteOnly | IO_Truncate))
|
||||
return false;
|
||||
f.writeBlock(cs.data(), cs.length());
|
||||
f.close();
|
||||
|
||||
TQString str = qvar("QMAKE_CC") + ' ' + fname + " -o " + out + ' ' + flags;
|
||||
int r = doCommand(str);
|
||||
if(r == 0 && retcode)
|
||||
*retcode = doCommand(TQString("./") + out);
|
||||
dir.remove(fname);
|
||||
dir.remove(out);
|
||||
if(r != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkHeader(const TQString &path, const TQString &h)
|
||||
{
|
||||
TQFileInfo fi(path + '/' + h);
|
||||
if(fi.exists())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findHeader(const TQString &h, const TQStringList &ext, TQString *inc)
|
||||
{
|
||||
if(checkHeader("/usr/include", h)) {
|
||||
*inc = "";
|
||||
return true;
|
||||
}
|
||||
TQStringList dirs;
|
||||
dirs += "/usr/local/include";
|
||||
dirs += ext;
|
||||
for(TQStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) {
|
||||
if(checkHeader(*it, h)) {
|
||||
*inc = *it;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkLibrary(const TQString &path, const TQString &name)
|
||||
{
|
||||
TQString str =
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
|
||||
TQString extra;
|
||||
if(!path.isEmpty())
|
||||
extra += TQString("-L") + path + ' ';
|
||||
extra += TQString("-l") + name;
|
||||
if(!doCompileAndLink(str, extra))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool findLibrary(const TQString &name, TQString *lib)
|
||||
{
|
||||
if(checkLibrary("", name)) {
|
||||
*lib = "";
|
||||
return true;
|
||||
}
|
||||
if(checkLibrary("/usr/local/lib", name)) {
|
||||
*lib = "/usr/local/lib";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void addDefine(const TQString &str)
|
||||
{
|
||||
if(DEFINES.isEmpty())
|
||||
DEFINES = str;
|
||||
else
|
||||
DEFINES += TQString(" ") + str;
|
||||
}
|
||||
|
||||
void addLib(const TQString &str)
|
||||
{
|
||||
if(LIBS.isEmpty())
|
||||
LIBS = str;
|
||||
else
|
||||
LIBS += TQString(" ") + str;
|
||||
}
|
||||
|
||||
void addIncludePath(const TQString &str)
|
||||
{
|
||||
if(INCLUDEPATH.isEmpty())
|
||||
INCLUDEPATH = str;
|
||||
else
|
||||
INCLUDEPATH += TQString(" ") + str;
|
||||
}
|
||||
|
||||
void addExtra(const TQString &str)
|
||||
{
|
||||
extra += str + '\n';
|
||||
}
|
||||
|
||||
TQString DEFINES;
|
||||
TQString INCLUDEPATH;
|
||||
TQString LIBS;
|
||||
TQString extra;
|
||||
|
||||
private:
|
||||
ConfObjList list;
|
||||
TQDict<TQString> vars;
|
||||
TQString blank;
|
||||
};
|
||||
|
||||
ConfObj::ConfObj(Conf *c)
|
||||
{
|
||||
conf = c;
|
||||
conf->added(this);
|
||||
required = false;
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
ConfObj::~ConfObj()
|
||||
{
|
||||
}
|
||||
|
||||
#include"modules.cpp"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// main
|
||||
//----------------------------------------------------------------------------
|
||||
int main()
|
||||
{
|
||||
Conf *conf = new Conf;
|
||||
ConfObj *o;
|
||||
o = 0;
|
||||
#include"modules_new.cpp"
|
||||
|
||||
printf("ok\n");
|
||||
bool success = false;
|
||||
if(conf->exec()) {
|
||||
TQFile f("conf.pri");
|
||||
if(!f.open(IO_WriteOnly | IO_Truncate)) {
|
||||
printf("Error writing %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
|
||||
TQString str;
|
||||
str += "# qconf\n";
|
||||
str += "QT_PATH_PLUGINS = " + TQString(tqInstallPathPlugins()) + '\n';
|
||||
if(!conf->DEFINES.isEmpty())
|
||||
str += "DEFINES += " + conf->DEFINES + '\n';
|
||||
if(!conf->INCLUDEPATH.isEmpty())
|
||||
str += "INCLUDEPATH += " + conf->INCLUDEPATH + '\n';
|
||||
if(!conf->LIBS.isEmpty())
|
||||
str += "LIBS += " + conf->LIBS + '\n';
|
||||
if(!conf->extra.isEmpty())
|
||||
str += conf->extra;
|
||||
str += '\n';
|
||||
|
||||
char *p = getenv("BINDIR");
|
||||
if(p) {
|
||||
str += TQString("target.path = ") + p + '\n';
|
||||
str += "INSTALLS += target\n";
|
||||
}
|
||||
|
||||
TQCString cs = str.latin1();
|
||||
f.writeBlock(cs.data(), cs.length());
|
||||
f.close();
|
||||
success = true;
|
||||
}
|
||||
delete conf;
|
||||
|
||||
if(success)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
EOT
|
||||
cat >$1/conf.pro <<EOT
|
||||
TEMPLATE = app
|
||||
CONFIG += qt x11 thread console
|
||||
TARGET = conf
|
||||
INCLUDEPATH += '/usr/include/tqt'
|
||||
|
||||
DEFINES += X11_INC='"\$\$QMAKE_INCDIR_X11"'
|
||||
DEFINES += X11_LIBDIR='"\$\$QMAKE_LIBDIR_X11"'
|
||||
DEFINES += X11_LIB='"\$\$QMAKE_LIBS_X11"'
|
||||
DEFINES += CC='"\$\$QMAKE_CC"'
|
||||
|
||||
SOURCES += conf.cpp
|
||||
|
||||
EOT
|
||||
}
|
||||
|
||||
export PREFIX
|
||||
export QTDIR
|
||||
rm -rf .qconftemp
|
||||
(
|
||||
mkdir .qconftemp
|
||||
gen_files .qconftemp
|
||||
cd .qconftemp
|
||||
$qm conf.pro >/dev/null
|
||||
QTDIR=$QTDIR make clean >/dev/null 2>&1
|
||||
QTDIR=$QTDIR make >../conf.log 2>&1
|
||||
)
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
rm -rf .qconftemp
|
||||
echo fail
|
||||
echo
|
||||
echo "There was an error compiling 'conf'. Be sure you have a proper"
|
||||
echo "TQt 3.x Multithreaded (MT) build environment set up."
|
||||
if [ ! -f "$QTDIR/lib/libtqt-mt.so.3" ]; then
|
||||
echo
|
||||
echo "One possible reason is that you don't have"
|
||||
echo "libtqt-mt.so.3 installed in $QTDIR/lib/."
|
||||
fi
|
||||
echo
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
.qconftemp/conf
|
||||
ret="$?"
|
||||
if [ "$ret" = "1" ]; then
|
||||
rm -rf .qconftemp
|
||||
echo
|
||||
exit 1;
|
||||
else
|
||||
if [ "$ret" != "0" ]; then
|
||||
rm -rf .qconftemp
|
||||
echo fail
|
||||
echo
|
||||
echo Unexpected error launching 'conf'
|
||||
echo
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
rm -rf .qconftemp
|
||||
|
||||
if [ -x "./qcextra" ]; then
|
||||
./qcextra
|
||||
fi
|
||||
# run qmake
|
||||
$qm qca.pro
|
||||
if [ "$?" != "0" ]; then
|
||||
echo
|
||||
exit 1;
|
||||
fi
|
||||
cat >Makefile.tmp <<EOT
|
||||
export QTDIR = $QTDIR
|
||||
EOT
|
||||
cat Makefile >> Makefile.tmp
|
||||
rm -f Makefile
|
||||
cp -f Makefile.tmp Makefile
|
||||
rm -f Makefile.tmp
|
||||
|
||||
echo
|
||||
echo Good, your configure finished. Now run \'make\'.
|
||||
echo
|
@ -0,0 +1,65 @@
|
||||
#include<tqdom.h>
|
||||
#include<tqfile.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
TQCA::Cert readCertXml(const TQDomElement &e)
|
||||
{
|
||||
TQCA::Cert cert;
|
||||
// there should be one child data tag
|
||||
TQDomElement data = e.elementsByTagName("data").item(0).toElement();
|
||||
if(!data.isNull())
|
||||
cert.fromDER(Base64::stringToArray(data.text()));
|
||||
return cert;
|
||||
}
|
||||
|
||||
void showCertInfo(const TQCA::Cert &cert)
|
||||
{
|
||||
printf(" CN: %s\n", cert.subject()["CN"].latin1());
|
||||
printf(" Valid from: %s, until %s\n",
|
||||
cert.notBefore().toString().latin1(),
|
||||
cert.notAfter().toString().latin1());
|
||||
printf(" PEM:\n%s\n", cert.toPEM().latin1());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if(!TQCA::isSupported(TQCA::CAP_X509)) {
|
||||
printf("X509 not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// open the Psi rootcerts file
|
||||
TQFile f("/usr/local/share/psi/certs/rootcert.xml");
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("unable to open %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
TQDomDocument doc;
|
||||
doc.setContent(&f);
|
||||
f.close();
|
||||
|
||||
TQDomElement base = doc.documentElement();
|
||||
if(base.tagName() != "store") {
|
||||
printf("wrong format of %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
TQDomNodeList cl = base.elementsByTagName("certificate");
|
||||
if(cl.count() == 0) {
|
||||
printf("no certs found in %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int n = 0; n < (int)cl.count(); ++n) {
|
||||
printf("-- Cert %d --\n", n);
|
||||
TQCA::Cert cert = readCertXml(cl.item(n).toElement());
|
||||
if(cert.isNull()) {
|
||||
printf("error reading cert\n");
|
||||
continue;
|
||||
}
|
||||
showCertInfo(cert);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = certtest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp certtest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,89 @@
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
static TQCString arrayToCString(const TQByteArray &);
|
||||
static TQByteArray cstringToArray(const TQCString &);
|
||||
static void doDynTest(TQCA::Cipher *c, const TQString &name, const TQCString &cs);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQCA::init();
|
||||
TQCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
// AES128 test
|
||||
if(!TQCA::isSupported(TQCA::CAP_AES128))
|
||||
printf("AES128 not supported!\n");
|
||||
else {
|
||||
// encrypt
|
||||
TQByteArray key = TQCA::AES128::generateKey();
|
||||
TQByteArray iv = TQCA::AES128::generateIV();
|
||||
printf("aes128:key:%s\n", TQCA::arrayToHex(key).latin1());
|
||||
printf("aes128:iv:%s\n", TQCA::arrayToHex(iv).latin1());
|
||||
TQCA::AES128 c(TQCA::Encrypt, TQCA::CBC, key, iv);
|
||||
c.update(cstringToArray(cs));
|
||||
TQByteArray f = c.final();
|
||||
TQString result = TQCA::arrayToHex(f);
|
||||
printf(">aes128(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
|
||||
// decrypt
|
||||
TQCA::AES128 d(TQCA::Decrypt, TQCA::CBC, key, iv);
|
||||
d.update(f);
|
||||
TQCString dec = arrayToCString(d.final());
|
||||
printf("<aes128(\"%s\") = [%s]\n", result.latin1(), dec.data());
|
||||
}
|
||||
|
||||
// BlowFish, TripleDES, and AES256 tested dynamically
|
||||
if(!TQCA::isSupported(TQCA::CAP_BlowFish))
|
||||
printf("BlowFish not supported!\n");
|
||||
else
|
||||
doDynTest(new TQCA::BlowFish, "bfish", cs);
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_TripleDES))
|
||||
printf("TripleDES not supported!\n");
|
||||
else
|
||||
doDynTest(new TQCA::TripleDES, "3des", cs);
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_AES256))
|
||||
printf("AES256 not supported!\n");
|
||||
else
|
||||
doDynTest(new TQCA::AES256, "aes256", cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TQCString arrayToCString(const TQByteArray &a)
|
||||
{
|
||||
TQCString cs;
|
||||
cs.resize(a.size()+1);
|
||||
memcpy(cs.data(), a.data(), a.size());
|
||||
return cs;
|
||||
}
|
||||
|
||||
TQByteArray cstringToArray(const TQCString &cs)
|
||||
{
|
||||
TQByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
return a;
|
||||
}
|
||||
|
||||
void doDynTest(TQCA::Cipher *c, const TQString &name, const TQCString &cs)
|
||||
{
|
||||
// encrypt
|
||||
TQByteArray key = c->dyn_generateKey();
|
||||
TQByteArray iv = c->dyn_generateIV();
|
||||
printf("%s:key:%s\n", name.latin1(), TQCA::arrayToHex(key).latin1());
|
||||
printf("%s:iv:%s\n", name.latin1(), TQCA::arrayToHex(iv).latin1());
|
||||
c->reset(TQCA::Encrypt, TQCA::CBC, key, iv);
|
||||
c->update(cstringToArray(cs));
|
||||
TQByteArray f = c->final();
|
||||
TQString result = TQCA::arrayToHex(f);
|
||||
printf(">%s(\"%s\") = [%s]\n", name.latin1(), cs.data(), result.latin1());
|
||||
|
||||
// decrypt
|
||||
c->reset(TQCA::Decrypt, TQCA::CBC, key, iv);
|
||||
c->update(f);
|
||||
TQCString dec = arrayToCString(c->final());
|
||||
printf("<%s(\"%s\") = [%s]\n", name.latin1(), result.latin1(), dec.data());
|
||||
delete c;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = ciphertest
|
||||
|
||||
SOURCES += ciphertest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* base64.cpp - Base64 converting functions
|
||||
* Copyright (C) 2003 Justin Karneges
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include"base64.h"
|
||||
|
||||
//! \class Base64 base64.h
|
||||
//! \brief Base64 conversion functions.
|
||||
//!
|
||||
//! Converts Base64 data between arrays and strings.
|
||||
//!
|
||||
//! \code
|
||||
//! #include "base64.h"
|
||||
//!
|
||||
//! ...
|
||||
//!
|
||||
//! // encode a block of data into base64
|
||||
//! TQByteArray block(1024);
|
||||
//! TQByteArray enc = Base64::encode(block);
|
||||
//!
|
||||
//! \endcode
|
||||
|
||||
//!
|
||||
//! Encodes array \a s and returns the result.
|
||||
TQByteArray Base64::encode(const TQByteArray &s)
|
||||
{
|
||||
int i;
|
||||
int len = s.size();
|
||||
char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
int a, b, c;
|
||||
|
||||
TQByteArray p((len+2)/3*4);
|
||||
int at = 0;
|
||||
for( i = 0; i < len; i += 3 ) {
|
||||
a = ((unsigned char)s[i] & 3) << 4;
|
||||
if(i + 1 < len) {
|
||||
a += (unsigned char)s[i + 1] >> 4;
|
||||
b = ((unsigned char)s[i + 1] & 0xF) << 2;
|
||||
if(i + 2 < len) {
|
||||
b += (unsigned char)s[i + 2] >> 6;
|
||||
c = (unsigned char)s[i + 2] & 0x3F;
|
||||
}
|
||||
else
|
||||
c = 64;
|
||||
}
|
||||
else
|
||||
b = c = 64;
|
||||
|
||||
p[at++] = tbl[(unsigned char)s[i] >> 2];
|
||||
p[at++] = tbl[a];
|
||||
p[at++] = tbl[b];
|
||||
p[at++] = tbl[c];
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//!
|
||||
//! Decodes array \a s and returns the result.
|
||||
TQByteArray Base64::decode(const TQByteArray &s)
|
||||
{
|
||||
// return value
|
||||
TQByteArray p;
|
||||
|
||||
// -1 specifies invalid
|
||||
// 64 specifies eof
|
||||
// everything else specifies data
|
||||
|
||||
char tbl[] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
|
||||
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1,
|
||||
-1, 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,-1,-1,-1,-1,-1,
|
||||
-1,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,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
};
|
||||
|
||||
// this should be a multiple of 4
|
||||
int len = s.size();
|
||||
|
||||
if(len % 4)
|
||||
return p;
|
||||
|
||||
p.resize(len / 4 * 3);
|
||||
|
||||
int i;
|
||||
int at = 0;
|
||||
|
||||
int a, b, c, d;
|
||||
c = d = 0;
|
||||
|
||||
for( i = 0; i < len; i += 4 ) {
|
||||
a = tbl[(int)s[i]];
|
||||
b = tbl[(int)s[i + 1]];
|
||||
c = tbl[(int)s[i + 2]];
|
||||
d = tbl[(int)s[i + 3]];
|
||||
if((a == 64 || b == 64) || (a < 0 || b < 0 || c < 0 || d < 0)) {
|
||||
p.resize(0);
|
||||
return p;
|
||||
}
|
||||
p[at++] = ((a & 0x3F) << 2) | ((b >> 4) & 0x03);
|
||||
p[at++] = ((b & 0x0F) << 4) | ((c >> 2) & 0x0F);
|
||||
p[at++] = ((c & 0x03) << 6) | ((d >> 0) & 0x3F);
|
||||
}
|
||||
|
||||
if(c & 64)
|
||||
p.resize(at - 2);
|
||||
else if(d & 64)
|
||||
p.resize(at - 1);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//!
|
||||
//! Encodes array \a a and returns the result as a string.
|
||||
TQString Base64::arrayToString(const TQByteArray &a)
|
||||
{
|
||||
TQByteArray b = encode(a);
|
||||
TQCString c;
|
||||
c.resize(b.size()+1);
|
||||
memcpy(c.data(), b.data(), b.size());
|
||||
return TQString::fromLatin1(c);
|
||||
}
|
||||
|
||||
//!
|
||||
//! Decodes string \a s and returns the result as an array.
|
||||
TQByteArray Base64::stringToArray(const TQString &s)
|
||||
{
|
||||
if(s.isEmpty())
|
||||
return TQByteArray();
|
||||
const char *c = s.latin1();
|
||||
int len = strlen(c);
|
||||
TQByteArray b(len);
|
||||
memcpy(b.data(), c, len);
|
||||
TQByteArray a = decode(b);
|
||||
return a;
|
||||
}
|
||||
|
||||
//!
|
||||
//! Encodes string \a s and returns the result as a string.
|
||||
TQString Base64::encodeString(const TQString &s)
|
||||
{
|
||||
TQCString c = s.utf8();
|
||||
int len = c.length();
|
||||
TQByteArray b(len);
|
||||
memcpy(b.data(), c.data(), len);
|
||||
return arrayToString(b);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* base64.h - Base64 converting functions
|
||||
* Copyright (C) 2003 Justin Karneges
|
||||
*
|
||||
* 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 CS_BASE64_H
|
||||
#define CS_BASE64_H
|
||||
|
||||
#include<qstring.h>
|
||||
|
||||
class Base64
|
||||
{
|
||||
public:
|
||||
static TQByteArray encode(const TQByteArray &);
|
||||
static TQByteArray decode(const TQByteArray &);
|
||||
static TQString arrayToString(const TQByteArray &);
|
||||
static TQByteArray stringToArray(const TQString &);
|
||||
static TQString encodeString(const TQString &);
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,7 @@
|
||||
# change/remove these entries, depending on the installation prefix
|
||||
INCLUDEPATH += /usr/local/include
|
||||
LIBS += -L/usr/local/lib
|
||||
|
||||
# link
|
||||
LIBS += -lqca
|
||||
|
@ -0,0 +1,11 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += \
|
||||
hashtest \
|
||||
ciphertest \
|
||||
rsatest \
|
||||
certtest \
|
||||
ssltest \
|
||||
sslservtest \
|
||||
sasltest
|
||||
|
@ -0,0 +1,25 @@
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQCA::init();
|
||||
TQCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_SHA1))
|
||||
printf("SHA1 not supported!\n");
|
||||
else {
|
||||
TQString result = TQCA::SHA1::hashToString(cs);
|
||||
printf("sha1(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
}
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_MD5))
|
||||
printf("MD5 not supported!\n");
|
||||
else {
|
||||
TQString result = TQCA::MD5::hashToString(cs);
|
||||
printf("md5(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = hashtest
|
||||
|
||||
SOURCES += hashtest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,86 @@
|
||||
#include<tqfile.h>
|
||||
#include<tqfileinfo.h>
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
//#define USE_FILE
|
||||
|
||||
TQCA::RSAKey readKeyFile(const TQString &name)
|
||||
{
|
||||
TQCA::RSAKey k;
|
||||
TQFile f(name);
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("Unable to open %s\n", name.latin1());
|
||||
return k;
|
||||
}
|
||||
TQByteArray der = f.readAll();
|
||||
f.close();
|
||||
printf("Read %s [%d bytes]\n", name.latin1(), der.size());
|
||||
|
||||
if(!k.fromDER(der)) {
|
||||
printf("%s: Error importing DER format.\n", name.latin1());
|
||||
return k;
|
||||
}
|
||||
char *yes = "yes";
|
||||
char *no = "no";
|
||||
printf("Successfully imported %s (enc=%s, dec=%s)\n",
|
||||
name.latin1(),
|
||||
k.havePublic() ? yes : no,
|
||||
k.havePrivate() ? yes : no);
|
||||
|
||||
printf("Converting to DER: %d bytes\n", k.toDER().size());
|
||||
printf("Converting to PEM:\n%s\n", k.toPEM().latin1());
|
||||
return k;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQCA::init();
|
||||
TQCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_RSA))
|
||||
printf("RSA not supported!\n");
|
||||
else {
|
||||
#ifdef USE_FILE
|
||||
TQCA::RSAKey pubkey = readKeyFile("keypublic.der");
|
||||
if(pubkey.isNull())
|
||||
return 1;
|
||||
TQCA::RSAKey seckey = readKeyFile("keyprivate.der");
|
||||
if(seckey.isNull())
|
||||
return 1;
|
||||
#else
|
||||
TQCA::RSAKey seckey = TQCA::RSA::generateKey(1024);
|
||||
if(seckey.isNull())
|
||||
return 1;
|
||||
TQCA::RSAKey pubkey = seckey;
|
||||
#endif
|
||||
// encrypt some data
|
||||
TQByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
|
||||
TQCA::RSA op;
|
||||
op.setKey(pubkey);
|
||||
TQByteArray result;
|
||||
if(!op.encrypt(a, &result)) {
|
||||
printf("Error encrypting.\n");
|
||||
return 1;
|
||||
}
|
||||
TQString rstr = TQCA::arrayToHex(result);
|
||||
printf(">rsa(\"%s\") = [%s]\n", cs.data(), rstr.latin1());
|
||||
|
||||
// now decrypt it
|
||||
op.setKey(seckey);
|
||||
TQByteArray dec;
|
||||
if(!op.decrypt(result, &dec)) {
|
||||
printf("Error decrypting.\n");
|
||||
return 1;
|
||||
}
|
||||
TQCString dstr;
|
||||
dstr.resize(dec.size()+1);
|
||||
memcpy(dstr.data(), dec.data(), dec.size());
|
||||
printf("<rsa(\"%s\") = [%s]\n", rstr.latin1(), dstr.data());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = rsatest
|
||||
|
||||
SOURCES += rsatest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,615 @@
|
||||
#include<tqapplication.h>
|
||||
#include<tqtimer.h>
|
||||
#include<tqsocket.h>
|
||||
#include<tqserversocket.h>
|
||||
#include<stdio.h>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include<unistd.h>
|
||||
#endif
|
||||
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
#define PROTO_NAME "foo"
|
||||
#define PROTO_PORT 8001
|
||||
|
||||
static TQString prompt(const TQString &s)
|
||||
{
|
||||
printf("* %s ", s.latin1());
|
||||
fflush(stdout);
|
||||
char line[256];
|
||||
fgets(line, 255, stdin);
|
||||
TQString result = line;
|
||||
if(result[result.length()-1] == '\n')
|
||||
result.truncate(result.length()-1);
|
||||
return result;
|
||||
}
|
||||
|
||||
class ClientTest : public TQObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClientTest()
|
||||
{
|
||||
sock = new TQSocket;
|
||||
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
|
||||
connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
|
||||
|
||||
sasl = new QCA::SASL;
|
||||
connect(sasl, SIGNAL(clientFirstStep(const TQString &, const TQByteArray *)), SLOT(sasl_clientFirstStep(const TQString &, const TQByteArray *)));
|
||||
connect(sasl, SIGNAL(nextStep(const TQByteArray &)), SLOT(sasl_nextStep(const TQByteArray &)));
|
||||
connect(sasl, SIGNAL(needParams(bool, bool, bool, bool)), SLOT(sasl_needParams(bool, bool, bool, bool)));
|
||||
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
|
||||
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
|
||||
connect(sasl, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
|
||||
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
|
||||
}
|
||||
|
||||
~ClientTest()
|
||||
{
|
||||
delete sock;
|
||||
delete sasl;
|
||||
}
|
||||
|
||||
void start(const TQString &_host, int port, const TQString &user="", const TQString &pass="")
|
||||
{
|
||||
mode = 0;
|
||||
host = _host;
|
||||
sock->connectToHost(host, port);
|
||||
sasl->setMinimumSSF(0);
|
||||
sasl->setMaximumSSF(256);
|
||||
|
||||
if(!user.isEmpty()) {
|
||||
sasl->setUsername(user);
|
||||
sasl->setAuthzid(user);
|
||||
}
|
||||
if(!pass.isEmpty())
|
||||
sasl->setPassword(pass);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_connected()
|
||||
{
|
||||
printf("Connected to server. Awaiting mechanism list...\n");
|
||||
}
|
||||
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("Connection closed by peer.\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
void sock_error(int x)
|
||||
{
|
||||
TQString s;
|
||||
if(x == TQSocket::ErrConnectionRefused)
|
||||
s = "connection refused or timed out";
|
||||
else if(x == TQSocket::ErrHostNotFound)
|
||||
s = "host not found";
|
||||
else if(x == TQSocket::ErrSocketRead)
|
||||
s = "read error";
|
||||
|
||||
printf("Socket error: %s\n", s.latin1());
|
||||
quit();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(mode == 2) {
|
||||
int avail = sock->bytesAvailable();
|
||||
TQByteArray a(avail);
|
||||
int n = sock->readBlock(a.data(), a.size());
|
||||
a.resize(n);
|
||||
printf("Read %d bytes\n", a.size());
|
||||
sasl->writeIncoming(a);
|
||||
}
|
||||
else {
|
||||
if(sock->canReadLine()) {
|
||||
TQString line = sock->readLine();
|
||||
line.truncate(line.length()-1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sasl_clientFirstStep(const TQString &mech, const TQByteArray *clientInit)
|
||||
{
|
||||
printf("Choosing mech: %s\n", mech.latin1());
|
||||
TQString line = mech;
|
||||
if(clientInit) {
|
||||
TQCString cs(clientInit->data(), clientInit->size()+1);
|
||||
line += ' ';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_nextStep(const TQByteArray &stepData)
|
||||
{
|
||||
TQCString cs(stepData.data(), stepData.size()+1);
|
||||
TQString line = "C";
|
||||
if(!stepData.isEmpty()) {
|
||||
line += ',';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_needParams(bool user, bool authzid, bool pass, bool realm)
|
||||
{
|
||||
TQString username;
|
||||
if(user || authzid)
|
||||
username = prompt("Username:");
|
||||
if(user) {
|
||||
sasl->setUsername(username);
|
||||
}
|
||||
if(authzid) {
|
||||
sasl->setAuthzid(username);
|
||||
}
|
||||
if(pass) {
|
||||
sasl->setPassword(prompt("Password (not hidden!) :"));
|
||||
}
|
||||
if(realm) {
|
||||
sasl->setRealm(prompt("Realm:"));
|
||||
}
|
||||
sasl->continueAfterParams();
|
||||
}
|
||||
|
||||
void sasl_authenticated()
|
||||
{
|
||||
printf("SASL success!\n");
|
||||
printf("SSF: %d\n", sasl->ssf());
|
||||
}
|
||||
|
||||
void sasl_readyRead()
|
||||
{
|
||||
TQByteArray a = sasl->read();
|
||||
int oldsize = inbuf.size();
|
||||
inbuf.resize(oldsize + a.size());
|
||||
memcpy(inbuf.data() + oldsize, a.data(), a.size());
|
||||
processInbuf();
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing(int)
|
||||
{
|
||||
TQByteArray a = sasl->readOutgoing();
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void sasl_error(int)
|
||||
{
|
||||
printf("SASL error!\n");
|
||||
quit();
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
TQSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
int mode;
|
||||
TQString host;
|
||||
TQByteArray inbuf;
|
||||
|
||||
void processInbuf()
|
||||
{
|
||||
TQStringList list;
|
||||
for(int n = 0; n < (int)inbuf.size(); ++n) {
|
||||
if(inbuf[n] == '\n') {
|
||||
TQCString cs(inbuf.data(), n+1);
|
||||
char *p = inbuf.data();
|
||||
++n;
|
||||
int x = inbuf.size() - n;
|
||||
memmove(p, p + n, x);
|
||||
inbuf.resize(x);
|
||||
list += TQString::fromUtf8(cs);
|
||||
// start over, basically
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
|
||||
for(TQStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
|
||||
handleLine(*it);
|
||||
}
|
||||
|
||||
void handleLine(const TQString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", line.latin1());
|
||||
if(mode == 0) {
|
||||
// first line is the method list
|
||||
TQStringList mechlist = TQStringList::split(' ', line);
|
||||
++mode;
|
||||
|
||||
// kick off the client
|
||||
sasl->setAllowAnonymous(false);
|
||||
if(!sasl->startClient(PROTO_NAME, host, mechlist)) {
|
||||
printf("Error starting client!\n");
|
||||
quit();
|
||||
}
|
||||
}
|
||||
else if(mode == 1) {
|
||||
TQString type, rest;
|
||||
int n = line.find(',');
|
||||
if(n != -1) {
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n+1);
|
||||
}
|
||||
else {
|
||||
type = line;
|
||||
rest = "";
|
||||
}
|
||||
|
||||
if(type == "C") {
|
||||
TQCString cs = rest.latin1();
|
||||
TQByteArray buf(cs.length());
|
||||
memcpy(buf.data(), cs.data(), buf.size());
|
||||
sasl->putStep(buf);
|
||||
}
|
||||
else if(type == "E") {
|
||||
printf("Authentication failed.\n");
|
||||
quit();
|
||||
return;
|
||||
}
|
||||
else if(type == "A") {
|
||||
printf("Authentication success.\n");
|
||||
++mode;
|
||||
sock_readyRead(); // any extra data?
|
||||
return;
|
||||
}
|
||||
else {
|
||||
printf("Bad format from peer, closing.\n");
|
||||
quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
void sendLine(const TQString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", line.latin1());
|
||||
TQString s = line + '\n';
|
||||
TQCString cs = s.latin1();
|
||||
if(mode == 2) {
|
||||
TQByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
sasl->write(a);
|
||||
}
|
||||
else
|
||||
sock->writeBlock(cs.data(), cs.length());
|
||||
}
|
||||
};
|
||||
|
||||
class ServerTest : public QServerSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ServerTest(const TQString &_str, int _port) : QServerSocket(_port), port(_port)
|
||||
{
|
||||
sock = 0;
|
||||
sasl = 0;
|
||||
realm = TQString::null;
|
||||
str = _str;
|
||||
}
|
||||
|
||||
~ServerTest()
|
||||
{
|
||||
delete sock;
|
||||
delete sasl;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if(!ok()) {
|
||||
printf("Error binding to port %d!\n", port);
|
||||
TTQTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
char myhostname[256];
|
||||
int r = gethostname(myhostname, sizeof(myhostname)-1);
|
||||
if(r == -1) {
|
||||
printf("Error getting hostname!\n");
|
||||
TTQTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
host = myhostname;
|
||||
printf("Listening on %s:%d ...\n", host.latin1(), port);
|
||||
}
|
||||
|
||||
void newConnection(int s)
|
||||
{
|
||||
// Note: only 1 connection supported at a time in this example!
|
||||
if(sock) {
|
||||
TQSocket tmp;
|
||||
tmp.setSocket(s);
|
||||
printf("Connection ignored, already have one active.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Connection received! Starting SASL handshake...\n");
|
||||
|
||||
sock = new TQSocket;
|
||||
connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
|
||||
connect(sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
|
||||
|
||||
sasl = new QCA::SASL;
|
||||
connect(sasl, SIGNAL(authCheck(const TQString &, const TQString &)), SLOT(sasl_authCheck(const TQString &, const TQString &)));
|
||||
connect(sasl, SIGNAL(nextStep(const TQByteArray &)), SLOT(sasl_nextStep(const TQByteArray &)));
|
||||
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
|
||||
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
|
||||
connect(sasl, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
|
||||
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
|
||||
|
||||
sock->setSocket(s);
|
||||
mode = 0;
|
||||
inbuf.resize(0);
|
||||
|
||||
sasl->setMinimumSSF(0);
|
||||
sasl->setMaximumSSF(256);
|
||||
|
||||
TQStringList mechlist;
|
||||
if(!sasl->startServer(PROTO_NAME, host, realm, &mechlist)) {
|
||||
printf("Error starting server!\n");
|
||||
quit();
|
||||
}
|
||||
TQString str;
|
||||
bool first = true;
|
||||
for(TQStringList::ConstIterator it = mechlist.begin(); it != mechlist.end(); ++it) {
|
||||
if(!first)
|
||||
str += ' ';
|
||||
str += *it;
|
||||
first = false;
|
||||
}
|
||||
sendLine(str);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("Connection closed by peer.\n");
|
||||
close();
|
||||
}
|
||||
|
||||
void sock_error(int x)
|
||||
{
|
||||
TQString s;
|
||||
if(x == TQSocket::ErrConnectionRefused)
|
||||
s = "connection refused or timed out";
|
||||
else if(x == TQSocket::ErrHostNotFound)
|
||||
s = "host not found";
|
||||
else if(x == TQSocket::ErrSocketRead)
|
||||
s = "read error";
|
||||
|
||||
printf("Socket error: %s\n", s.latin1());
|
||||
close();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(sock->canReadLine()) {
|
||||
TQString line = sock->readLine();
|
||||
line.truncate(line.length()-1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
void sock_bytesWritten(int x)
|
||||
{
|
||||
if(mode == 2) {
|
||||
toWrite -= x;
|
||||
if(toWrite <= 0) {
|
||||
printf("Sent, closing.\n");
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sasl_nextStep(const TQByteArray &stepData)
|
||||
{
|
||||
TQCString cs(stepData.data(), stepData.size()+1);
|
||||
TQString line = "C";
|
||||
if(!stepData.isEmpty()) {
|
||||
line += ',';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_authCheck(const TQString &user, const TQString &authzid)
|
||||
{
|
||||
printf("AuthCheck: User: [%s], Authzid: [%s]\n", user.latin1(), authzid.latin1());
|
||||
sasl->continueAfterAuthCheck();
|
||||
}
|
||||
|
||||
void sasl_authenticated()
|
||||
{
|
||||
sendLine("A");
|
||||
printf("Authentication success.\n");
|
||||
++mode;
|
||||
printf("SSF: %d\n", sasl->ssf());
|
||||
sendLine(str);
|
||||
}
|
||||
|
||||
void sasl_readyRead()
|
||||
{
|
||||
TQByteArray a = sasl->read();
|
||||
int oldsize = inbuf.size();
|
||||
inbuf.resize(oldsize + a.size());
|
||||
memcpy(inbuf.data() + oldsize, a.data(), a.size());
|
||||
processInbuf();
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing(int)
|
||||
{
|
||||
TQByteArray a = sasl->readOutgoing();
|
||||
toWrite = a.size();
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void sasl_error(int x)
|
||||
{
|
||||
if(x == QCA::SASL::ErrAuth) {
|
||||
sendLine("E");
|
||||
printf("Authentication failed.\n");
|
||||
close();
|
||||
}
|
||||
else {
|
||||
printf("SASL security layer error!\n");
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TQSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
TQString host, realm;
|
||||
int port;
|
||||
int mode;
|
||||
TQString str;
|
||||
TQByteArray inbuf;
|
||||
int toWrite;
|
||||
|
||||
void processInbuf()
|
||||
{
|
||||
}
|
||||
|
||||
void handleLine(const TQString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", line.latin1());
|
||||
if(mode == 0) {
|
||||
int n = line.find(' ');
|
||||
if(n != -1) {
|
||||
TQString mech = line.mid(0, n);
|
||||
TQCString cs = line.mid(n+1).latin1();
|
||||
TQByteArray clientInit(cs.length());
|
||||
memcpy(clientInit.data(), cs.data(), clientInit.size());
|
||||
sasl->putServerFirstStep(mech, clientInit);
|
||||
}
|
||||
else
|
||||
sasl->putServerFirstStep(line);
|
||||
++mode;
|
||||
}
|
||||
else if(mode == 1) {
|
||||
TQString type, rest;
|
||||
int n = line.find(',');
|
||||
if(n != -1) {
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n+1);
|
||||
}
|
||||
else {
|
||||
type = line;
|
||||
rest = "";
|
||||
}
|
||||
|
||||
if(type == "C") {
|
||||
TQCString cs = rest.latin1();
|
||||
TQByteArray buf(cs.length());
|
||||
memcpy(buf.data(), cs.data(), buf.size());
|
||||
sasl->putStep(buf);
|
||||
}
|
||||
else {
|
||||
printf("Bad format from peer, closing.\n");
|
||||
close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendLine(const TQString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", line.latin1());
|
||||
TQString s = line + '\n';
|
||||
TQCString cs = s.latin1();
|
||||
if(mode == 2) {
|
||||
TQByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
sasl->write(a);
|
||||
}
|
||||
else
|
||||
sock->writeBlock(cs.data(), cs.length());
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
sock->deleteLater();
|
||||
sock = 0;
|
||||
delete sasl;
|
||||
sasl = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#include"sasltest.moc"
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("usage: sasltest client [host] [user] [pass]\n");
|
||||
printf(" sasltest server [string]\n\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQApplication app(argc, argv, false);
|
||||
|
||||
TQString host, user, pass;
|
||||
TQString str = "Hello, World";
|
||||
bool server;
|
||||
if(argc < 2) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
TQString arg = argv[1];
|
||||
if(arg == "client") {
|
||||
if(argc < 3) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
host = argv[2];
|
||||
if(argc >= 4)
|
||||
user = argv[3];
|
||||
if(argc >= 5)
|
||||
pass = argv[4];
|
||||
server = false;
|
||||
}
|
||||
else if(arg == "server") {
|
||||
if(argc >= 3)
|
||||
str = argv[2];
|
||||
server = true;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_SASL)) {
|
||||
printf("SASL not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(server) {
|
||||
ServerTest *s = new ServerTest(str, PROTO_PORT);
|
||||
TQObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start();
|
||||
app.exec();
|
||||
delete s;
|
||||
}
|
||||
else {
|
||||
ClientTest *c = new ClientTest;
|
||||
TQObject::connect(c, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
c->start(host, PROTO_PORT, user, pass);
|
||||
app.exec();
|
||||
delete c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = sasltest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp sasltest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,294 @@
|
||||
#include<tqapplication.h>
|
||||
#include<tqfile.h>
|
||||
#include<tqsocket.h>
|
||||
#include<tqserversocket.h>
|
||||
#include<tqvaluelist.h>
|
||||
#include<tqtimer.h>
|
||||
#include"qca.h"
|
||||
|
||||
char pemdata_cert[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDbjCCAtegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBhzELMAkGA1UEBhMCVVMx\n"
|
||||
"EzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNVBAcTBklydmluZTEYMBYGA1UEChMP\n"
|
||||
"RXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtleGFtcGxlLmNvbTEiMCAGCSqGSIb3\n"
|
||||
"DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbTAeFw0wMzA3MjQwNzMwMDBaFw0wMzA4\n"
|
||||
"MjMwNzMwMDBaMIGHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEP\n"
|
||||
"MA0GA1UEBxMGSXJ2aW5lMRgwFgYDVQQKEw9FeGFtcGxlIENvbXBhbnkxFDASBgNV\n"
|
||||
"BAMTC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu\n"
|
||||
"Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCobzCF268K2sRp473gvBTT\n"
|
||||
"4AgSL1kjeF8N57vxS1P8zWrWMXNs4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwW\n"
|
||||
"WZToesxebu3m9VeA8dqWyOaUMjoxAcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8m\n"
|
||||
"a+AAPByfTORbzpSTmXAQAwIDAQABo4HnMIHkMB0GA1UdDgQWBBTvFierzLmmYMq0\n"
|
||||
"cB/+5rK1bNR56zCBtAYDVR0jBIGsMIGpgBTvFierzLmmYMq0cB/+5rK1bNR566GB\n"
|
||||
"jaSBijCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNV\n"
|
||||
"BAcTBklydmluZTEYMBYGA1UEChMPRXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtl\n"
|
||||
"eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbYIB\n"
|
||||
"ADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAGqGhXf7xNOnYNtFO7gz\n"
|
||||
"K6RdZGHFI5q1DAEz4hhNBC9uElh32XGX4wN7giz3zLC8v9icL/W4ff/K5NDfv3Gf\n"
|
||||
"gQe/+Wo9Be3H3ul6uwPPFnx4+PIOF2a5TW99H9smyxWdNjnFtcUte4al3RszcMWG\n"
|
||||
"x3iqsWosGtj6F+ridmKoqKLu\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
char pemdata_privkey[] =
|
||||
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
"MIICXAIBAAKBgQCobzCF268K2sRp473gvBTT4AgSL1kjeF8N57vxS1P8zWrWMXNs\n"
|
||||
"4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwWWZToesxebu3m9VeA8dqWyOaUMjox\n"
|
||||
"AcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8ma+AAPByfTORbzpSTmXAQAwIDAQAB\n"
|
||||
"AoGAP83u+aYghuIcaWhmM03MLf69z/WztKYSi/fu0BcS977w67bL3MC9CVPoPRB/\n"
|
||||
"0nLSt/jZIuRzHKUCYfXLerSU7v0oXDTy6GPzWMh/oXIrpF0tYNbwWF7LSq2O2gGZ\n"
|
||||
"XtA9MSmUNNJaKzQQeXjqdVFOY8A0Pho+k2KByBiCi+ChkcECQQDRUuyX0+PKJtA2\n"
|
||||
"M36BOTFpy61BAv+JRlXUnHuevOfQWl6NR6YGygqCyH1sWtP1sa9S4wWys3DFH+5A\n"
|
||||
"DkuAqk7zAkEAzf4eUH2hp5CIMsXH+WpIzKj09oY1it2CAKjVq4rUELf8iXvmGoFl\n"
|
||||
"000spua4MjHNUYm7LR0QaKesKrMyGZUesQJAL8aLdYPJI+SD9Tr/jqLtIkZ4frQe\n"
|
||||
"eshw4pvsoyheiHF3zyshO791crAr4EVCx3sMlxB1xnmqLXPCPyCEHxO//QJBAIBY\n"
|
||||
"IYkjDZJ6ofGIe1UyXJNvfdkPu9J+ut4wU5jjEcgs6mK62J6RGuFxhy2iOQfFMdjo\n"
|
||||
"yL+OCUg7mDCun7uCxrECQAtSvnLOFMjO5qExRjFtwi+b1rcSekd3Osk/izyRFSzg\n"
|
||||
"Or+AL56/EKfiogNnFipgaXIbb/xj785Cob6v96XoW1I=\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
class LayerTracker
|
||||
{
|
||||
public:
|
||||
struct Item
|
||||
{
|
||||
int plain;
|
||||
int encoded;
|
||||
};
|
||||
|
||||
LayerTracker()
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
p = 0;
|
||||
list.clear();
|
||||
}
|
||||
|
||||
void addPlain(int plain)
|
||||
{
|
||||
p += plain;
|
||||
}
|
||||
|
||||
void specifyEncoded(int encoded, int plain)
|
||||
{
|
||||
// can't specify more bytes than we have
|
||||
if(plain > p)
|
||||
plain = p;
|
||||
p -= plain;
|
||||
Item i;
|
||||
i.plain = plain;
|
||||
i.encoded = encoded;
|
||||
list += i;
|
||||
}
|
||||
|
||||
int finished(int encoded)
|
||||
{
|
||||
int plain = 0;
|
||||
for(TQValueList<Item>::Iterator it = list.begin(); it != list.end();) {
|
||||
Item &i = *it;
|
||||
|
||||
// not enough?
|
||||
if(encoded < i.encoded) {
|
||||
i.encoded -= encoded;
|
||||
break;
|
||||
}
|
||||
|
||||
encoded -= i.encoded;
|
||||
plain += i.plain;
|
||||
it = list.remove(it);
|
||||
}
|
||||
return plain;
|
||||
}
|
||||
|
||||
int p;
|
||||
TQValueList<Item> list;
|
||||
};
|
||||
|
||||
class SecureServerTest : public QServerSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum { Idle, Handshaking, Active, Closing };
|
||||
|
||||
SecureServerTest(int _port) : QServerSocket(_port), port(_port)
|
||||
{
|
||||
sock = new TQSocket;
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
|
||||
connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
|
||||
connect(sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
|
||||
|
||||
ssl = new QCA::TLS;
|
||||
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
|
||||
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
|
||||
connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
|
||||
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
|
||||
connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
|
||||
|
||||
cert.fromPEM(pemdata_cert);
|
||||
privkey.fromPEM(pemdata_privkey);
|
||||
|
||||
mode = Idle;
|
||||
}
|
||||
|
||||
~SecureServerTest()
|
||||
{
|
||||
delete ssl;
|
||||
delete sock;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if(cert.isNull() || privkey.isNull()) {
|
||||
printf("Error loading cert and/or private key!\n");
|
||||
TTQTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
if(!ok()) {
|
||||
printf("Error binding to port %d!\n", port);
|
||||
TTQTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
printf("Listening on port %d ...\n", port);
|
||||
}
|
||||
|
||||
void newConnection(int s)
|
||||
{
|
||||
// Note: only 1 connection supported at a time in this example!
|
||||
if(sock->isOpen()) {
|
||||
TQSocket tmp;
|
||||
tmp.setSocket(s);
|
||||
printf("throwing away extra connection\n");
|
||||
return;
|
||||
}
|
||||
mode = Handshaking;
|
||||
sock->setSocket(s);
|
||||
printf("Connection received! Starting TLS handshake...\n");
|
||||
ssl->setCertificate(cert, privkey);
|
||||
ssl->startServer();
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_readyRead()
|
||||
{
|
||||
TQByteArray buf(sock->bytesAvailable());
|
||||
int num = sock->readBlock(buf.data(), buf.size());
|
||||
if(num < (int)buf.size())
|
||||
buf.resize(num);
|
||||
ssl->writeIncoming(buf);
|
||||
}
|
||||
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("Connection closed.\n");
|
||||
}
|
||||
|
||||
void sock_bytesWritten(int x)
|
||||
{
|
||||
if(mode == Active && sent) {
|
||||
int bytes = layer.finished(x);
|
||||
bytesLeft -= bytes;
|
||||
|
||||
if(bytesLeft == 0) {
|
||||
mode = Closing;
|
||||
printf("SSL shutdown\n");
|
||||
ssl->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sock_error(int)
|
||||
{
|
||||
printf("Socket error.\n");
|
||||
}
|
||||
|
||||
void ssl_handshaken()
|
||||
{
|
||||
printf("Successful SSL handshake. Waiting for newline.\n");
|
||||
layer.reset();
|
||||
bytesLeft = 0;
|
||||
sent = false;
|
||||
mode = Active;
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
TQByteArray a = ssl->read();
|
||||
TQString str =
|
||||
"<html>\n"
|
||||
"<head><title>Test</title></head>\n"
|
||||
"<body>this is only a test</body>\n"
|
||||
"</html>\n";
|
||||
TQCString cs = str.latin1();
|
||||
TQByteArray b(cs.length());
|
||||
memcpy(b.data(), cs.data(), b.size());
|
||||
|
||||
printf("Sending test response...\n");
|
||||
sent = true;
|
||||
layer.addPlain(b.size());
|
||||
ssl->write(b);
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing(int plainBytes)
|
||||
{
|
||||
TQByteArray a = ssl->readOutgoing();
|
||||
layer.specifyEncoded(a.size(), plainBytes);
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void ssl_closed()
|
||||
{
|
||||
printf("Closing.\n");
|
||||
sock->close();
|
||||
}
|
||||
|
||||
void ssl_error(int x)
|
||||
{
|
||||
if(x == QCA::TLS::ErrHandshake) {
|
||||
printf("SSL Handshake Error! Closing.\n");
|
||||
sock->close();
|
||||
}
|
||||
else {
|
||||
printf("SSL Error! Closing.\n");
|
||||
sock->close();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int port;
|
||||
TQSocket *sock;
|
||||
QCA::TLS *ssl;
|
||||
QCA::Cert cert;
|
||||
QCA::RSAKey privkey;
|
||||
|
||||
bool sent;
|
||||
int mode;
|
||||
int bytesLeft;
|
||||
LayerTracker layer;
|
||||
};
|
||||
|
||||
#include"sslservtest.moc"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQApplication app(argc, argv, false);
|
||||
int port = argc > 1 ? TQString(argv[1]).toInt() : 8000;
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_TLS)) {
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureServerTest *s = new SecureServerTest(port);
|
||||
TQObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start();
|
||||
app.exec();
|
||||
delete s;
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = sslservtest
|
||||
|
||||
SOURCES += sslservtest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,276 @@
|
||||
#include<tqapplication.h>
|
||||
#include<tqdom.h>
|
||||
#include<tqfile.h>
|
||||
#include<tqsocket.h>
|
||||
#include<tqptrlist.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
TQCA::Cert readCertXml(const TQDomElement &e)
|
||||
{
|
||||
TQCA::Cert cert;
|
||||
// there should be one child data tag
|
||||
TQDomElement data = e.elementsByTagName("data").item(0).toElement();
|
||||
if(!data.isNull())
|
||||
cert.fromDER(Base64::stringToArray(data.text()));
|
||||
return cert;
|
||||
}
|
||||
|
||||
void showCertInfo(const TQCA::Cert &cert)
|
||||
{
|
||||
printf("-- Cert --\n");
|
||||
printf(" CN: %s\n", cert.subject()["CN"].latin1());
|
||||
printf(" Valid from: %s, until %s\n",
|
||||
cert.notBefore().toString().latin1(),
|
||||
cert.notAfter().toString().latin1());
|
||||
printf(" PEM:\n%s\n", cert.toPEM().latin1());
|
||||
}
|
||||
|
||||
TQPtrList<TQCA::Cert> getRootCerts(const TQString &store)
|
||||
{
|
||||
TQPtrList<TQCA::Cert> list;
|
||||
|
||||
// open the Psi rootcerts file
|
||||
TQFile f(store);
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("unable to open %s\n", f.name().latin1());
|
||||
return list;
|
||||
}
|
||||
TQDomDocument doc;
|
||||
doc.setContent(&f);
|
||||
f.close();
|
||||
|
||||
TQDomElement base = doc.documentElement();
|
||||
if(base.tagName() != "store") {
|
||||
printf("wrong format of %s\n", f.name().latin1());
|
||||
return list;
|
||||
}
|
||||
TQDomNodeList cl = base.elementsByTagName("certificate");
|
||||
if(cl.count() == 0) {
|
||||
printf("no certs found in %s\n", f.name().latin1());
|
||||
return list;
|
||||
}
|
||||
|
||||
int num = 0;
|
||||
for(int n = 0; n < (int)cl.count(); ++n) {
|
||||
TQCA::Cert *cert = new TQCA::Cert(readCertXml(cl.item(n).toElement()));
|
||||
if(cert->isNull()) {
|
||||
printf("error reading cert\n");
|
||||
delete cert;
|
||||
continue;
|
||||
}
|
||||
|
||||
++num;
|
||||
list.append(cert);
|
||||
}
|
||||
printf("imported %d root certs\n", num);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
TQString resultToString(int result)
|
||||
{
|
||||
TQString s;
|
||||
switch(result) {
|
||||
case TQCA::TLS::NoCert:
|
||||
s = TQObject::tr("No certificate presented.");
|
||||
break;
|
||||
case TQCA::TLS::Valid:
|
||||
break;
|
||||
case TQCA::TLS::HostMismatch:
|
||||
s = TQObject::tr("Hostname mismatch.");
|
||||
break;
|
||||
case TQCA::TLS::Rejected:
|
||||
s = TQObject::tr("Root CA rejects the specified purpose.");
|
||||
break;
|
||||
case TQCA::TLS::Untrusted:
|
||||
s = TQObject::tr("Not trusted for the specified purpose.");
|
||||
break;
|
||||
case TQCA::TLS::SignatureFailed:
|
||||
s = TQObject::tr("Invalid signature.");
|
||||
break;
|
||||
case TQCA::TLS::InvalidCA:
|
||||
s = TQObject::tr("Invalid CA certificate.");
|
||||
break;
|
||||
case TQCA::TLS::InvalidPurpose:
|
||||
s = TQObject::tr("Invalid certificate purpose.");
|
||||
break;
|
||||
case TQCA::TLS::SelfSigned:
|
||||
s = TQObject::tr("Certificate is self-signed.");
|
||||
break;
|
||||
case TQCA::TLS::Revoked:
|
||||
s = TQObject::tr("Certificate has been revoked.");
|
||||
break;
|
||||
case TQCA::TLS::PathLengthExceeded:
|
||||
s = TQObject::tr("Maximum cert chain length exceeded.");
|
||||
break;
|
||||
case TQCA::TLS::Expired:
|
||||
s = TQObject::tr("Certificate has expired.");
|
||||
break;
|
||||
case TQCA::TLS::Unknown:
|
||||
default:
|
||||
s = TQObject::tr("General validation error.");
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
class SecureTest : public TQObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SecureTest()
|
||||
{
|
||||
sock = new TQSocket;
|
||||
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
|
||||
connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
|
||||
|
||||
ssl = new TQCA::TLS;
|
||||
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
|
||||
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
|
||||
connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
|
||||
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
|
||||
connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
|
||||
|
||||
rootCerts.setAutoDelete(true);
|
||||
rootCerts = getRootCerts("/usr/local/share/psi/certs/rootcert.xml");
|
||||
}
|
||||
|
||||
~SecureTest()
|
||||
{
|
||||
delete ssl;
|
||||
delete sock;
|
||||
}
|
||||
|
||||
void start(const TQString &_host)
|
||||
{
|
||||
int n = _host.find(':');
|
||||
int port;
|
||||
if(n != -1) {
|
||||
host = _host.mid(0, n);
|
||||
port = _host.mid(n+1).toInt();
|
||||
}
|
||||
else {
|
||||
host = _host;
|
||||
port = 443;
|
||||
}
|
||||
|
||||
printf("Trying %s:%d...\n", host.latin1(), port);
|
||||
sock->connectToHost(host, port);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_connected()
|
||||
{
|
||||
printf("Connected, starting TLS handshake...\n");
|
||||
ssl->setCertificateStore(rootCerts);
|
||||
ssl->startClient(host);
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
TQByteArray buf(sock->bytesAvailable());
|
||||
int num = sock->readBlock(buf.data(), buf.size());
|
||||
if(num < (int)buf.size())
|
||||
buf.resize(num);
|
||||
ssl->writeIncoming(buf);
|
||||
}
|
||||
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("\nConnection closed.\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
void sock_error(int)
|
||||
{
|
||||
printf("\nSocket error.\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
void ssl_handshaken()
|
||||
{
|
||||
cert = ssl->peerCertificate();
|
||||
int vr = ssl->certificateValidityResult();
|
||||
|
||||
printf("Successful SSL handshake.\n");
|
||||
if(!cert.isNull())
|
||||
showCertInfo(cert);
|
||||
if(vr == TQCA::TLS::Valid)
|
||||
printf("Valid certificate.\n");
|
||||
else
|
||||
printf("Invalid certificate: %s\n", resultToString(vr).latin1());
|
||||
|
||||
printf("Let's try a GET request now.\n");
|
||||
TQString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
|
||||
TQCString cs = req.latin1();
|
||||
TQByteArray buf(cs.length());
|
||||
memcpy(buf.data(), cs.data(), buf.size());
|
||||
ssl->write(buf);
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
TQByteArray a = ssl->read();
|
||||
TQCString cs;
|
||||
cs.resize(a.size()+1);
|
||||
memcpy(cs.data(), a.data(), a.size());
|
||||
printf("%s", cs.data());
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing(int)
|
||||
{
|
||||
TQByteArray a = ssl->readOutgoing();
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void ssl_closed()
|
||||
{
|
||||
printf("SSL session closed\n");
|
||||
}
|
||||
|
||||
void ssl_error(int x)
|
||||
{
|
||||
if(x == TQCA::TLS::ErrHandshake) {
|
||||
printf("SSL Handshake Error!\n");
|
||||
quit();
|
||||
}
|
||||
else {
|
||||
printf("SSL Error!\n");
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TQString host;
|
||||
TQSocket *sock;
|
||||
TQCA::TLS *ssl;
|
||||
TQCA::Cert cert;
|
||||
TQPtrList<TQCA::Cert> rootCerts;
|
||||
};
|
||||
|
||||
#include"ssltest.moc"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TQApplication app(argc, argv, false);
|
||||
TQString host = argc > 1 ? argv[1] : "andbit.net";
|
||||
|
||||
if(!TQCA::isSupported(TQCA::CAP_TLS)) {
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureTest *s = new SecureTest;
|
||||
TQObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start(host);
|
||||
app.exec();
|
||||
delete s;
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread console
|
||||
TARGET = ssltest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp ssltest.cpp
|
||||
include(../examples.pri)
|
@ -0,0 +1,33 @@
|
||||
# qca qmake profile
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += qt thread release
|
||||
TARGET = qca
|
||||
|
||||
MOC_DIR = .moc
|
||||
OBJECTS_DIR = .obj
|
||||
UI_DIR = .ui
|
||||
|
||||
VER_MAJ = 1
|
||||
VER_MIN = 0
|
||||
|
||||
# make DLL
|
||||
win32:{
|
||||
CONFIG += dll
|
||||
DEFINES += QCA_MAKEDLL
|
||||
}
|
||||
|
||||
QCA_CPP = src
|
||||
INCLUDEPATH += $$QCA_CPP
|
||||
INCLUDEPATH += /usr/include/tqt
|
||||
|
||||
HEADERS += \
|
||||
$$QCA_CPP/qca.h \
|
||||
$$QCA_CPP/qcaprovider.h
|
||||
|
||||
SOURCES += \
|
||||
$$QCA_CPP/qca.cpp
|
||||
|
||||
include(conf.pri)
|
||||
include(extra.pri)
|
||||
|
@ -0,0 +1,5 @@
|
||||
<qconf>
|
||||
<name>Qt Cryptographic Architecture (QCA)</name>
|
||||
<profile>qca.pro</profile>
|
||||
<nobindir/>
|
||||
</qconf>
|
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat >extra.pri <<EOT
|
||||
target.path=$PREFIX/lib
|
||||
INSTALLS += target
|
||||
|
||||
incfiles.path=$PREFIX/include
|
||||
incfiles.files=src/qca.h
|
||||
INSTALLS += incfiles
|
||||
|
||||
INSTALL_ROOT = $PREFIX
|
||||
|
||||
EOT
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* qca.h - Qt Cryptographic Architecture
|
||||
* Copyright (C) 2003 Justin Karneges
|
||||
*
|
||||
* 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 TQCA_H
|
||||
#define TQCA_H
|
||||
|
||||
#include<tqstring.h>
|
||||
#include<tqcstring.h>
|
||||
#include<tqdatetime.h>
|
||||
#include<tqmap.h>
|
||||
#include<tqptrlist.h>
|
||||
#include<tqobject.h>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
# ifndef TQCA_STATIC
|
||||
# ifdef TQCA_MAKEDLL
|
||||
# define TQCA_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define TQCA_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#ifndef TQCA_EXPORT
|
||||
#define TQCA_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
# ifdef TQCA_PLUGIN_DLL
|
||||
# define TQCA_PLUGIN_EXPORT extern "C" __declspec(dllexport)
|
||||
# else
|
||||
# define TQCA_PLUGIN_EXPORT extern "C" __declspec(dllimport)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef TQCA_PLUGIN_EXPORT
|
||||
#define TQCA_PLUGIN_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
class TQHostAddress;
|
||||
class TQStringList;
|
||||
|
||||
class TQCAProvider;
|
||||
class TQCA_HashContext;
|
||||
class TQCA_CipherContext;
|
||||
class TQCA_CertContext;
|
||||
|
||||
namespace TQCA
|
||||
{
|
||||
enum {
|
||||
CAP_SHA1 = 0x0001,
|
||||
CAP_SHA256 = 0x0002,
|
||||
CAP_MD5 = 0x0004,
|
||||
CAP_BlowFish = 0x0008,
|
||||
CAP_TripleDES = 0x0010,
|
||||
CAP_AES128 = 0x0020,
|
||||
CAP_AES256 = 0x0040,
|
||||
CAP_RSA = 0x0080,
|
||||
CAP_X509 = 0x0100,
|
||||
CAP_TLS = 0x0200,
|
||||
CAP_SASL = 0x0400
|
||||
};
|
||||
|
||||
enum {
|
||||
CBC = 0x0001,
|
||||
CFB = 0x0002
|
||||
};
|
||||
|
||||
enum {
|
||||
Encrypt = 0x0001,
|
||||
Decrypt = 0x0002
|
||||
};
|
||||
|
||||
TQCA_EXPORT void init();
|
||||
TQCA_EXPORT bool isSupported(int capabilities);
|
||||
TQCA_EXPORT void insertProvider(TQCAProvider *);
|
||||
TQCA_EXPORT void unloadAllPlugins();
|
||||
|
||||
TQCA_EXPORT TQString arrayToHex(const TQByteArray &);
|
||||
TQCA_EXPORT TQByteArray hexToArray(const TQString &);
|
||||
|
||||
class TQCA_EXPORT Hash
|
||||
{
|
||||
public:
|
||||
Hash(const Hash &);
|
||||
Hash & operator=(const Hash &);
|
||||
~Hash();
|
||||
|
||||
void clear();
|
||||
void update(const TQByteArray &a);
|
||||
TQByteArray final();
|
||||
|
||||
protected:
|
||||
Hash(TQCA_HashContext *);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TQCA_EXPORT HashStatic
|
||||
{
|
||||
public:
|
||||
HashStatic<T>() {}
|
||||
|
||||
static TQByteArray hash(const TQByteArray &a)
|
||||
{
|
||||
T obj;
|
||||
obj.update(a);
|
||||
return obj.final();
|
||||
}
|
||||
|
||||
static TQByteArray hash(const TQCString &cs)
|
||||
{
|
||||
TQByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
return hash(a);
|
||||
}
|
||||
|
||||
static TQString hashToString(const TQByteArray &a)
|
||||
{
|
||||
return arrayToHex(hash(a));
|
||||
}
|
||||
|
||||
static TQString hashToString(const TQCString &cs)
|
||||
{
|
||||
return arrayToHex(hash(cs));
|
||||
}
|
||||
};
|
||||
|
||||
class TQCA_EXPORT Cipher
|
||||
{
|
||||
public:
|
||||
Cipher(const Cipher &);
|
||||
Cipher & operator=(const Cipher &);
|
||||
~Cipher();
|
||||
|
||||
TQByteArray dyn_generateKey(int size=-1) const;
|
||||
TQByteArray dyn_generateIV() const;
|
||||
void reset(int dir, int mode, const TQByteArray &key, const TQByteArray &iv, bool pad=true);
|
||||
bool update(const TQByteArray &a);
|
||||
TQByteArray final(bool *ok=0);
|
||||
|
||||
protected:
|
||||
Cipher(TQCA_CipherContext *, int dir, int mode, const TQByteArray &key, const TQByteArray &iv, bool pad);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TQCA_EXPORT CipherStatic
|
||||
{
|
||||
public:
|
||||
CipherStatic<T>() {}
|
||||
|
||||
static TQByteArray generateKey(int size=-1)
|
||||
{
|
||||
T obj;
|
||||
return obj.dyn_generateKey(size);
|
||||
}
|
||||
|
||||
static TQByteArray generateIV()
|
||||
{
|
||||
T obj;
|
||||
return obj.dyn_generateIV();
|
||||
}
|
||||
};
|
||||
|
||||
class TQCA_EXPORT SHA1 : public Hash, public HashStatic<SHA1>
|
||||
{
|
||||
public:
|
||||
SHA1();
|
||||
};
|
||||
|
||||
class TQCA_EXPORT SHA256 : public Hash, public HashStatic<SHA256>
|
||||
{
|
||||
public:
|
||||
SHA256();
|
||||
};
|
||||
|
||||
class TQCA_EXPORT MD5 : public Hash, public HashStatic<MD5>
|
||||
{
|
||||
public:
|
||||
MD5();
|
||||
};
|
||||
|
||||
class TQCA_EXPORT BlowFish : public Cipher, public CipherStatic<BlowFish>
|
||||
{
|
||||
public:
|
||||
BlowFish(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true);
|
||||
};
|
||||
|
||||
class TQCA_EXPORT TripleDES : public Cipher, public CipherStatic<TripleDES>
|
||||
{
|
||||
public:
|
||||
TripleDES(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true);
|
||||
};
|
||||
|
||||
class TQCA_EXPORT AES128 : public Cipher, public CipherStatic<AES128>
|
||||
{
|
||||
public:
|
||||
AES128(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true);
|
||||
};
|
||||
|
||||
class TQCA_EXPORT AES256 : public Cipher, public CipherStatic<AES256>
|
||||
{
|
||||
public:
|
||||
AES256(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true);
|
||||
};
|
||||
|
||||
class RSA;
|
||||
class TQCA_EXPORT RSAKey
|
||||
{
|
||||
public:
|
||||
RSAKey();
|
||||
RSAKey(const RSAKey &from);
|
||||
RSAKey & operator=(const RSAKey &from);
|
||||
~RSAKey();
|
||||
|
||||
bool isNull() const;
|
||||
bool havePublic() const;
|
||||
bool havePrivate() const;
|
||||
|
||||
TQByteArray toDER(bool publicOnly=false) const;
|
||||
bool fromDER(const TQByteArray &a);
|
||||
|
||||
TQString toPEM(bool publicOnly=false) const;
|
||||
bool fromPEM(const TQString &);
|
||||
|
||||
// only call if you know what you are doing
|
||||
bool fromNative(void *);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
|
||||
friend class RSA;
|
||||
friend class TLS;
|
||||
bool encrypt(const TQByteArray &a, TQByteArray *out, bool oaep) const;
|
||||
bool decrypt(const TQByteArray &a, TQByteArray *out, bool oaep) const;
|
||||
bool generate(unsigned int bits);
|
||||
};
|
||||
|
||||
class TQCA_EXPORT RSA
|
||||
{
|
||||
public:
|
||||
RSA();
|
||||
~RSA();
|
||||
|
||||
RSAKey key() const;
|
||||
void setKey(const RSAKey &);
|
||||
|
||||
bool encrypt(const TQByteArray &a, TQByteArray *out, bool oaep=false) const;
|
||||
bool decrypt(const TQByteArray &a, TQByteArray *out, bool oaep=false) const;
|
||||
|
||||
static RSAKey generateKey(unsigned int bits);
|
||||
|
||||
private:
|
||||
RSAKey v_key;
|
||||
};
|
||||
|
||||
typedef TQMap<TQString, TQString> CertProperties;
|
||||
class TQCA_EXPORT Cert
|
||||
{
|
||||
public:
|
||||
Cert();
|
||||
Cert(const Cert &);
|
||||
Cert & operator=(const Cert &);
|
||||
~Cert();
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
TQString commonName() const;
|
||||
TQString serialNumber() const;
|
||||
TQString subjectString() const;
|
||||
TQString issuerString() const;
|
||||
CertProperties subject() const;
|
||||
CertProperties issuer() const;
|
||||
TQDateTime notBefore() const;
|
||||
TQDateTime notAfter() const;
|
||||
|
||||
TQByteArray toDER() const;
|
||||
bool fromDER(const TQByteArray &a);
|
||||
|
||||
TQString toPEM() const;
|
||||
bool fromPEM(const TQString &);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
|
||||
friend class TLS;
|
||||
void fromContext(TQCA_CertContext *);
|
||||
};
|
||||
|
||||
class TQCA_EXPORT TLS : public TQObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Validity {
|
||||
NoCert,
|
||||
Valid,
|
||||
HostMismatch,
|
||||
Rejected,
|
||||
Untrusted,
|
||||
SignatureFailed,
|
||||
InvalidCA,
|
||||
InvalidPurpose,
|
||||
SelfSigned,
|
||||
Revoked,
|
||||
PathLengthExceeded,
|
||||
Expired,
|
||||
Unknown
|
||||
};
|
||||
enum Error { ErrHandshake, ErrCrypt };
|
||||
|
||||
TLS(TQObject *parent=0);
|
||||
~TLS();
|
||||
|
||||
void setCertificate(const Cert &cert, const RSAKey &key);
|
||||
void setCertificateStore(const TQPtrList<Cert> &store); // note: store must persist
|
||||
|
||||
void reset();
|
||||
bool startClient(const TQString &host="");
|
||||
bool startServer();
|
||||
void close();
|
||||
bool isHandshaken() const;
|
||||
|
||||
// plain (application side)
|
||||
void write(const TQByteArray &a);
|
||||
TQByteArray read();
|
||||
|
||||
// encoded (socket side)
|
||||
void writeIncoming(const TQByteArray &a);
|
||||
TQByteArray readOutgoing();
|
||||
TQByteArray readUnprocessed();
|
||||
|
||||
// cert related
|
||||
const Cert & peerCertificate() const;
|
||||
int certificateValidityResult() const;
|
||||
|
||||
signals:
|
||||
void handshaken();
|
||||
void readyRead();
|
||||
void readyReadOutgoing(int plainBytes);
|
||||
void closed();
|
||||
void error(int);
|
||||
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
class TQCA_EXPORT SASL : public TQObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Error { ErrAuth, ErrCrypt };
|
||||
enum ErrorCond {
|
||||
NoMech,
|
||||
BadProto,
|
||||
BadServ,
|
||||
BadAuth,
|
||||
NoAuthzid,
|
||||
TooWeak,
|
||||
NeedEncrypt,
|
||||
Expired,
|
||||
Disabled,
|
||||
NoUser,
|
||||
RemoteUnavail
|
||||
};
|
||||
SASL(TQObject *parent=0);
|
||||
~SASL();
|
||||
|
||||
static void setAppName(const TQString &name);
|
||||
|
||||
void reset();
|
||||
int errorCondition() const;
|
||||
|
||||
// options
|
||||
void setAllowPlain(bool);
|
||||
void setAllowAnonymous(bool);
|
||||
void setAllowActiveVulnerable(bool);
|
||||
void setAllowDictionaryVulnerable(bool);
|
||||
void setRequireForwardSecrecy(bool);
|
||||
void setRequirePassCredentials(bool);
|
||||
void setRequireMutualAuth(bool);
|
||||
|
||||
void setMinimumSSF(int);
|
||||
void setMaximumSSF(int);
|
||||
void setExternalAuthID(const TQString &authid);
|
||||
void setExternalSSF(int);
|
||||
|
||||
void setLocalAddr(const TQHostAddress &addr, TQ_UINT16 port);
|
||||
void setRemoteAddr(const TQHostAddress &addr, TQ_UINT16 port);
|
||||
|
||||
// initialize
|
||||
bool startClient(const TQString &service, const TQString &host, const TQStringList &mechlist, bool allowClientSendFirst=true);
|
||||
bool startServer(const TQString &service, const TQString &host, const TQString &realm, TQStringList *mechlist);
|
||||
|
||||
// authentication
|
||||
void putStep(const TQByteArray &stepData);
|
||||
void putServerFirstStep(const TQString &mech);
|
||||
void putServerFirstStep(const TQString &mech, const TQByteArray &clientInit);
|
||||
void setUsername(const TQString &user);
|
||||
void setAuthzid(const TQString &auth);
|
||||
void setPassword(const TQString &pass);
|
||||
void setRealm(const TQString &realm);
|
||||
void continueAfterParams();
|
||||
void continueAfterAuthCheck();
|
||||
|
||||
// security layer
|
||||
int ssf() const;
|
||||
void write(const TQByteArray &a);
|
||||
TQByteArray read();
|
||||
void writeIncoming(const TQByteArray &a);
|
||||
TQByteArray readOutgoing();
|
||||
|
||||
signals:
|
||||
// for authentication
|
||||
void clientFirstStep(const TQString &mech, const TQByteArray *clientInit);
|
||||
void nextStep(const TQByteArray &stepData);
|
||||
void needParams(bool user, bool authzid, bool pass, bool realm);
|
||||
void authCheck(const TQString &user, const TQString &authzid);
|
||||
void authenticated();
|
||||
|
||||
// for security layer
|
||||
void readyRead();
|
||||
void readyReadOutgoing(int plainBytes);
|
||||
|
||||
// error
|
||||
void error(int);
|
||||
|
||||
private slots:
|
||||
void tryAgain();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
|
||||
void handleServerFirstStep(int r);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* qcaprovider.h - QCA Plugin API
|
||||
* Copyright (C) 2003 Justin Karneges
|
||||
*
|
||||
* 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 TQCAPROVIDER_H
|
||||
#define TQCAPROVIDER_H
|
||||
|
||||
#include<tqglobal.h>
|
||||
#include<tqstring.h>
|
||||
#include<tqdatetime.h>
|
||||
#include<tqobject.h>
|
||||
#include<tqhostaddress.h>
|
||||
#include"qca.h"
|
||||
|
||||
#define TQCA_PLUGIN_VERSION 1
|
||||
|
||||
class TQCAProvider
|
||||
{
|
||||
public:
|
||||
TQCAProvider() {}
|
||||
virtual ~TQCAProvider() {}
|
||||
|
||||
virtual void init()=0;
|
||||
virtual int qcaVersion() const=0;
|
||||
virtual int capabilities() const=0;
|
||||
virtual void *context(int cap)=0;
|
||||
};
|
||||
|
||||
class TQCA_HashContext
|
||||
{
|
||||
public:
|
||||
virtual ~TQCA_HashContext() {}
|
||||
|
||||
virtual TQCA_HashContext *clone()=0;
|
||||
virtual void reset()=0;
|
||||
virtual void update(const char *in, unsigned int len)=0;
|
||||
virtual void final(TQByteArray *out)=0;
|
||||
};
|
||||
|
||||
class TQCA_CipherContext
|
||||
{
|
||||
public:
|
||||
virtual ~TQCA_CipherContext() {}
|
||||
|
||||
virtual TQCA_CipherContext *clone()=0;
|
||||
virtual int keySize()=0;
|
||||
virtual int blockSize()=0;
|
||||
virtual bool generateKey(char *out, int keysize=-1)=0;
|
||||
virtual bool generateIV(char *out)=0;
|
||||
|
||||
virtual bool setup(int dir, int mode, const char *key, int keysize, const char *iv, bool pad)=0;
|
||||
virtual bool update(const char *in, unsigned int len)=0;
|
||||
virtual bool final(TQByteArray *out)=0;
|
||||
};
|
||||
|
||||
class TQCA_RSAKeyContext
|
||||
{
|
||||
public:
|
||||
virtual ~TQCA_RSAKeyContext() {}
|
||||
|
||||
virtual TQCA_RSAKeyContext *clone() const=0;
|
||||
virtual bool isNull() const=0;
|
||||
virtual bool havePublic() const=0;
|
||||
virtual bool havePrivate() const=0;
|
||||
virtual bool createFromDER(const char *in, unsigned int len)=0;
|
||||
virtual bool createFromPEM(const char *in, unsigned int len)=0;
|
||||
virtual bool createFromNative(void *in)=0;
|
||||
virtual bool generate(unsigned int bits)=0;
|
||||
virtual bool toDER(TQByteArray *out, bool publicOnly)=0;
|
||||
virtual bool toPEM(TQByteArray *out, bool publicOnly)=0;
|
||||
|
||||
virtual bool encrypt(const TQByteArray &in, TQByteArray *out, bool oaep)=0;
|
||||
virtual bool decrypt(const TQByteArray &in, TQByteArray *out, bool oaep)=0;
|
||||
};
|
||||
|
||||
struct TQCA_CertProperty
|
||||
{
|
||||
TQString var;
|
||||
TQString val;
|
||||
};
|
||||
|
||||
class TQCA_CertContext
|
||||
{
|
||||
public:
|
||||
virtual ~TQCA_CertContext() {}
|
||||
|
||||
virtual TQCA_CertContext *clone() const=0;
|
||||
virtual bool isNull() const=0;
|
||||
virtual bool createFromDER(const char *in, unsigned int len)=0;
|
||||
virtual bool createFromPEM(const char *in, unsigned int len)=0;
|
||||
virtual bool toDER(TQByteArray *out)=0;
|
||||
virtual bool toPEM(TQByteArray *out)=0;
|
||||
|
||||
virtual TQString serialNumber() const=0;
|
||||
virtual TQString subjectString() const=0;
|
||||
virtual TQString issuerString() const=0;
|
||||
virtual TQValueList<TQCA_CertProperty> subject() const=0;
|
||||
virtual TQValueList<TQCA_CertProperty> issuer() const=0;
|
||||
virtual TQDateTime notBefore() const=0;
|
||||
virtual TQDateTime notAfter() const=0;
|
||||
virtual bool matchesAddress(const TQString &realHost) const=0;
|
||||
};
|
||||
|
||||
class TQCA_TLSContext
|
||||
{
|
||||
public:
|
||||
enum Result { Success, Error, Continue };
|
||||
virtual ~TQCA_TLSContext() {}
|
||||
|
||||
virtual void reset()=0;
|
||||
virtual bool startClient(const TQPtrList<TQCA_CertContext> &store, const TQCA_CertContext &cert, const TQCA_RSAKeyContext &key)=0;
|
||||
virtual bool startServer(const TQPtrList<TQCA_CertContext> &store, const TQCA_CertContext &cert, const TQCA_RSAKeyContext &key)=0;
|
||||
|
||||
virtual int handshake(const TQByteArray &in, TQByteArray *out)=0;
|
||||
virtual int shutdown(const TQByteArray &in, TQByteArray *out)=0;
|
||||
virtual bool encode(const TQByteArray &plain, TQByteArray *to_net, int *encoded)=0;
|
||||
virtual bool decode(const TQByteArray &from_net, TQByteArray *plain, TQByteArray *to_net)=0;
|
||||
virtual bool eof() const=0;
|
||||
virtual TQByteArray unprocessed()=0;
|
||||
|
||||
virtual TQCA_CertContext *peerCertificate() const=0;
|
||||
virtual int validityResult() const=0;
|
||||
};
|
||||
|
||||
struct TQCA_SASLHostPort
|
||||
{
|
||||
TQHostAddress addr;
|
||||
Q_UINT16 port;
|
||||
};
|
||||
|
||||
struct TQCA_SASLNeedParams
|
||||
{
|
||||
bool user, authzid, pass, realm;
|
||||
};
|
||||
|
||||
class TQCA_SASLContext
|
||||
{
|
||||
public:
|
||||
enum Result { Success, Error, NeedParams, AuthCheck, Continue };
|
||||
virtual ~TQCA_SASLContext() {}
|
||||
|
||||
// common
|
||||
virtual void reset()=0;
|
||||
virtual void setCoreProps(const TQString &service, const TQString &host, TQCA_SASLHostPort *local, TQCA_SASLHostPort *remote)=0;
|
||||
virtual void setSecurityProps(bool noPlain, bool noActive, bool noDict, bool noAnon, bool reqForward, bool reqCreds, bool reqMutual, int ssfMin, int ssfMax, const TQString &_ext_authid, int _ext_ssf)=0;
|
||||
virtual int security() const=0;
|
||||
virtual int errorCond() const=0;
|
||||
|
||||
// init / first step
|
||||
virtual bool clientStart(const TQStringList &mechlist)=0;
|
||||
virtual int clientFirstStep(bool allowClientSendFirst)=0;
|
||||
virtual bool serverStart(const TQString &realm, TQStringList *mechlist, const TQString &name)=0;
|
||||
virtual int serverFirstStep(const TQString &mech, const TQByteArray *in)=0;
|
||||
|
||||
// get / set params
|
||||
virtual TQCA_SASLNeedParams clientParamsNeeded() const=0;
|
||||
virtual void setClientParams(const TQString *user, const TQString *authzid, const TQString *pass, const TQString *realm)=0;
|
||||
virtual TQString username() const=0;
|
||||
virtual TQString authzid() const=0;
|
||||
|
||||
// continue steps
|
||||
virtual int nextStep(const TQByteArray &in)=0;
|
||||
virtual int tryAgain()=0;
|
||||
|
||||
// results
|
||||
virtual TQString mech() const=0;
|
||||
virtual const TQByteArray *clientInit() const=0;
|
||||
virtual TQByteArray result() const=0;
|
||||
|
||||
// security layer
|
||||
virtual bool encode(const TQByteArray &in, TQByteArray *out)=0;
|
||||
virtual bool decode(const TQByteArray &in, TQByteArray *out)=0;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in new issue