mirror of
https://github.com/QuasarApp/qca.git
synced 2025-04-27 20:14:32 +00:00
examples!
svn path=/trunk/kdesupport/qca/; revision=251709
This commit is contained in:
parent
772c9ba704
commit
471671d4f8
65
examples/certtest/certtest.cpp
Normal file
65
examples/certtest/certtest.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include<qdom.h>
|
||||
#include<qfile.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
QCA::Cert readCertXml(const QDomElement &e)
|
||||
{
|
||||
QCA::Cert cert;
|
||||
// there should be one child data tag
|
||||
QDomElement data = e.elementsByTagName("data").item(0).toElement();
|
||||
if(!data.isNull())
|
||||
cert.fromDER(Base64::stringToArray(data.text()));
|
||||
return cert;
|
||||
}
|
||||
|
||||
void showCertInfo(const QCA::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(!QCA::isSupported(QCA::CAP_X509)) {
|
||||
printf("X509 not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// open the Psi rootcerts file
|
||||
QFile f("/usr/local/share/psi/certs/rootcert.xml");
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("unable to open %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(&f);
|
||||
f.close();
|
||||
|
||||
QDomElement base = doc.documentElement();
|
||||
if(base.tagName() != "store") {
|
||||
printf("wrong format of %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
QDomNodeList 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);
|
||||
QCA::Cert cert = readCertXml(cl.item(n).toElement());
|
||||
if(cert.isNull()) {
|
||||
printf("error reading cert\n");
|
||||
continue;
|
||||
}
|
||||
showCertInfo(cert);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
8
examples/certtest/certtest.pro
Normal file
8
examples/certtest/certtest.pro
Normal file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = certtest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp certtest.cpp
|
||||
include(../examples.pri)
|
89
examples/ciphertest/ciphertest.cpp
Normal file
89
examples/ciphertest/ciphertest.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
static QCString arrayToCString(const QByteArray &);
|
||||
static QByteArray cstringToArray(const QCString &);
|
||||
static void doDynTest(QCA::Cipher *c, const QString &name, const QCString &cs);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::init();
|
||||
QCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
// AES128 test
|
||||
if(!QCA::isSupported(QCA::CAP_AES128))
|
||||
printf("AES128 not supported!\n");
|
||||
else {
|
||||
// encrypt
|
||||
QByteArray key = QCA::AES128::generateKey();
|
||||
QByteArray iv = QCA::AES128::generateIV();
|
||||
printf("aes128:key:%s\n", QCA::arrayToHex(key).latin1());
|
||||
printf("aes128:iv:%s\n", QCA::arrayToHex(iv).latin1());
|
||||
QCA::AES128 c(QCA::Encrypt, QCA::CBC, key, iv);
|
||||
c.update(cstringToArray(cs));
|
||||
QByteArray f = c.final();
|
||||
QString result = QCA::arrayToHex(f);
|
||||
printf(">aes128(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
|
||||
// decrypt
|
||||
QCA::AES128 d(QCA::Decrypt, QCA::CBC, key, iv);
|
||||
d.update(f);
|
||||
QCString dec = arrayToCString(d.final());
|
||||
printf("<aes128(\"%s\") = [%s]\n", result.latin1(), dec.data());
|
||||
}
|
||||
|
||||
// BlowFish, TripleDES, and AES256 tested dynamically
|
||||
if(!QCA::isSupported(QCA::CAP_BlowFish))
|
||||
printf("BlowFish not supported!\n");
|
||||
else
|
||||
doDynTest(new QCA::BlowFish, "bfish", cs);
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_TripleDES))
|
||||
printf("TripleDES not supported!\n");
|
||||
else
|
||||
doDynTest(new QCA::TripleDES, "3des", cs);
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_AES256))
|
||||
printf("AES256 not supported!\n");
|
||||
else
|
||||
doDynTest(new QCA::AES256, "aes256", cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QCString arrayToCString(const QByteArray &a)
|
||||
{
|
||||
QCString cs;
|
||||
cs.resize(a.size()+1);
|
||||
memcpy(cs.data(), a.data(), a.size());
|
||||
return cs;
|
||||
}
|
||||
|
||||
QByteArray cstringToArray(const QCString &cs)
|
||||
{
|
||||
QByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
return a;
|
||||
}
|
||||
|
||||
void doDynTest(QCA::Cipher *c, const QString &name, const QCString &cs)
|
||||
{
|
||||
// encrypt
|
||||
QByteArray key = c->dyn_generateKey();
|
||||
QByteArray iv = c->dyn_generateIV();
|
||||
printf("%s:key:%s\n", name.latin1(), QCA::arrayToHex(key).latin1());
|
||||
printf("%s:iv:%s\n", name.latin1(), QCA::arrayToHex(iv).latin1());
|
||||
c->reset(QCA::Encrypt, QCA::CBC, key, iv);
|
||||
c->update(cstringToArray(cs));
|
||||
QByteArray f = c->final();
|
||||
QString result = QCA::arrayToHex(f);
|
||||
printf(">%s(\"%s\") = [%s]\n", name.latin1(), cs.data(), result.latin1());
|
||||
|
||||
// decrypt
|
||||
c->reset(QCA::Decrypt, QCA::CBC, key, iv);
|
||||
c->update(f);
|
||||
QCString dec = arrayToCString(c->final());
|
||||
printf("<%s(\"%s\") = [%s]\n", name.latin1(), result.latin1(), dec.data());
|
||||
delete c;
|
||||
}
|
||||
|
6
examples/ciphertest/ciphertest.pro
Normal file
6
examples/ciphertest/ciphertest.pro
Normal file
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = ciphertest
|
||||
|
||||
SOURCES += ciphertest.cpp
|
||||
include(../examples.pri)
|
173
examples/common/base64.cpp
Normal file
173
examples/common/base64.cpp
Normal file
@ -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
|
||||
//! QByteArray block(1024);
|
||||
//! QByteArray enc = Base64::encode(block);
|
||||
//!
|
||||
//! \endcode
|
||||
|
||||
//!
|
||||
//! Encodes array \a s and returns the result.
|
||||
QByteArray Base64::encode(const QByteArray &s)
|
||||
{
|
||||
int i;
|
||||
int len = s.size();
|
||||
char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
int a, b, c;
|
||||
|
||||
QByteArray 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.
|
||||
QByteArray Base64::decode(const QByteArray &s)
|
||||
{
|
||||
// return value
|
||||
QByteArray 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.
|
||||
QString Base64::arrayToString(const QByteArray &a)
|
||||
{
|
||||
QByteArray b = encode(a);
|
||||
QCString c;
|
||||
c.resize(b.size()+1);
|
||||
memcpy(c.data(), b.data(), b.size());
|
||||
return QString::fromLatin1(c);
|
||||
}
|
||||
|
||||
//!
|
||||
//! Decodes string \a s and returns the result as an array.
|
||||
QByteArray Base64::stringToArray(const QString &s)
|
||||
{
|
||||
if(s.isEmpty())
|
||||
return QByteArray();
|
||||
const char *c = s.latin1();
|
||||
int len = strlen(c);
|
||||
QByteArray b(len);
|
||||
memcpy(b.data(), c, len);
|
||||
QByteArray a = decode(b);
|
||||
return a;
|
||||
}
|
||||
|
||||
//!
|
||||
//! Encodes string \a s and returns the result as a string.
|
||||
QString Base64::encodeString(const QString &s)
|
||||
{
|
||||
QCString c = s.utf8();
|
||||
int len = c.length();
|
||||
QByteArray b(len);
|
||||
memcpy(b.data(), c.data(), len);
|
||||
return arrayToString(b);
|
||||
}
|
36
examples/common/base64.h
Normal file
36
examples/common/base64.h
Normal file
@ -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 QByteArray encode(const QByteArray &);
|
||||
static QByteArray decode(const QByteArray &);
|
||||
static QString arrayToString(const QByteArray &);
|
||||
static QByteArray stringToArray(const QString &);
|
||||
static QString encodeString(const QString &);
|
||||
};
|
||||
|
||||
#endif
|
6
examples/examples.pri
Normal file
6
examples/examples.pri
Normal file
@ -0,0 +1,6 @@
|
||||
QCA_CPP = ../../src
|
||||
|
||||
INCLUDEPATH += $$QCA_CPP
|
||||
HEADERS += $$QCA_CPP/qca.h $$QCA_CPP/qcaprovider.h
|
||||
SOURCES += $$QCA_CPP/qca.cpp
|
||||
|
11
examples/examples.pro
Normal file
11
examples/examples.pro
Normal file
@ -0,0 +1,11 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += \
|
||||
hashtest \
|
||||
ciphertest \
|
||||
rsatest \
|
||||
certtest \
|
||||
ssltest \
|
||||
sslservtest \
|
||||
sasltest
|
||||
|
25
examples/hashtest/hashtest.cpp
Normal file
25
examples/hashtest/hashtest.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::init();
|
||||
QCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_SHA1))
|
||||
printf("SHA1 not supported!\n");
|
||||
else {
|
||||
QString result = QCA::SHA1::hashToString(cs);
|
||||
printf("sha1(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
}
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_MD5))
|
||||
printf("MD5 not supported!\n");
|
||||
else {
|
||||
QString result = QCA::MD5::hashToString(cs);
|
||||
printf("md5(\"%s\") = [%s]\n", cs.data(), result.latin1());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
6
examples/hashtest/hashtest.pro
Normal file
6
examples/hashtest/hashtest.pro
Normal file
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = hashtest
|
||||
|
||||
SOURCES += hashtest.cpp
|
||||
include(../examples.pri)
|
86
examples/rsatest/rsatest.cpp
Normal file
86
examples/rsatest/rsatest.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include<qfile.h>
|
||||
#include<qfileinfo.h>
|
||||
#include"qca.h"
|
||||
#include<stdio.h>
|
||||
|
||||
//#define USE_FILE
|
||||
|
||||
QCA::RSAKey readKeyFile(const QString &name)
|
||||
{
|
||||
QCA::RSAKey k;
|
||||
QFile f(name);
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("Unable to open %s\n", name.latin1());
|
||||
return k;
|
||||
}
|
||||
QByteArray 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)
|
||||
{
|
||||
QCA::init();
|
||||
QCString cs = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_RSA))
|
||||
printf("RSA not supported!\n");
|
||||
else {
|
||||
#ifdef USE_FILE
|
||||
QCA::RSAKey pubkey = readKeyFile("keypublic.der");
|
||||
if(pubkey.isNull())
|
||||
return 1;
|
||||
QCA::RSAKey seckey = readKeyFile("keyprivate.der");
|
||||
if(seckey.isNull())
|
||||
return 1;
|
||||
#else
|
||||
QCA::RSAKey seckey = QCA::RSA::generateKey(1024);
|
||||
if(seckey.isNull())
|
||||
return 1;
|
||||
QCA::RSAKey pubkey = seckey;
|
||||
#endif
|
||||
// encrypt some data
|
||||
QByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
|
||||
QCA::RSA op;
|
||||
op.setKey(pubkey);
|
||||
QByteArray result;
|
||||
if(!op.encrypt(a, &result)) {
|
||||
printf("Error encrypting.\n");
|
||||
return 1;
|
||||
}
|
||||
QString rstr = QCA::arrayToHex(result);
|
||||
printf(">rsa(\"%s\") = [%s]\n", cs.data(), rstr.latin1());
|
||||
|
||||
// now decrypt it
|
||||
op.setKey(seckey);
|
||||
QByteArray dec;
|
||||
if(!op.decrypt(result, &dec)) {
|
||||
printf("Error decrypting.\n");
|
||||
return 1;
|
||||
}
|
||||
QCString dstr;
|
||||
dstr.resize(dec.size()+1);
|
||||
memcpy(dstr.data(), dec.data(), dec.size());
|
||||
printf("<rsa(\"%s\") = [%s]\n", rstr.latin1(), dstr.data());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
6
examples/rsatest/rsatest.pro
Normal file
6
examples/rsatest/rsatest.pro
Normal file
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = rsatest
|
||||
|
||||
SOURCES += rsatest.cpp
|
||||
include(../examples.pri)
|
611
examples/sasltest/sasltest.cpp
Normal file
611
examples/sasltest/sasltest.cpp
Normal file
@ -0,0 +1,611 @@
|
||||
#include<qapplication.h>
|
||||
#include<qtimer.h>
|
||||
#include<qsocket.h>
|
||||
#include<qserversocket.h>
|
||||
#include<stdio.h>
|
||||
#include<unistd.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
#define PROTO_NAME "foo"
|
||||
#define PROTO_PORT 8001
|
||||
|
||||
static QString prompt(const QString &s)
|
||||
{
|
||||
printf("* %s ", s.latin1());
|
||||
fflush(stdout);
|
||||
char line[256];
|
||||
fgets(line, 255, stdin);
|
||||
QString result = line;
|
||||
if(result[result.length()-1] == '\n')
|
||||
result.truncate(result.length()-1);
|
||||
return result;
|
||||
}
|
||||
|
||||
class ClientTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClientTest()
|
||||
{
|
||||
sock = new QSocket;
|
||||
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 QString &, const QByteArray *)), SLOT(sasl_clientFirstStep(const QString &, const QByteArray *)));
|
||||
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
|
||||
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()), SLOT(sasl_readyReadOutgoing()));
|
||||
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
|
||||
}
|
||||
|
||||
~ClientTest()
|
||||
{
|
||||
delete sock;
|
||||
delete sasl;
|
||||
}
|
||||
|
||||
void start(const QString &_host, int port, const QString &user="", const QString &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)
|
||||
{
|
||||
QString s;
|
||||
if(x == QSocket::ErrConnectionRefused)
|
||||
s = "connection refused or timed out";
|
||||
else if(x == QSocket::ErrHostNotFound)
|
||||
s = "host not found";
|
||||
else if(x == QSocket::ErrSocketRead)
|
||||
s = "read error";
|
||||
|
||||
printf("Socket error: %s\n", s.latin1());
|
||||
quit();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(mode == 2) {
|
||||
int avail = sock->bytesAvailable();
|
||||
QByteArray 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()) {
|
||||
QString line = sock->readLine();
|
||||
line.truncate(line.length()-1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sasl_clientFirstStep(const QString &mech, const QByteArray *clientInit)
|
||||
{
|
||||
printf("Choosing mech: %s\n", mech.latin1());
|
||||
QString line = mech;
|
||||
if(clientInit) {
|
||||
QCString cs(clientInit->data(), clientInit->size()+1);
|
||||
line += ' ';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_nextStep(const QByteArray &stepData)
|
||||
{
|
||||
QCString cs(stepData.data(), stepData.size()+1);
|
||||
QString line = "C";
|
||||
if(!stepData.isEmpty()) {
|
||||
line += ',';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_needParams(bool user, bool authzid, bool pass, bool realm)
|
||||
{
|
||||
QString 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()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
int oldsize = inbuf.size();
|
||||
inbuf.resize(oldsize + a.size());
|
||||
memcpy(inbuf.data() + oldsize, a.data(), a.size());
|
||||
processInbuf();
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray a = sasl->readOutgoing();
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void sasl_error(int)
|
||||
{
|
||||
printf("SASL error!\n");
|
||||
quit();
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
QSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
int mode;
|
||||
QString host;
|
||||
QByteArray inbuf;
|
||||
|
||||
void processInbuf()
|
||||
{
|
||||
QStringList list;
|
||||
for(int n = 0; n < (int)inbuf.size(); ++n) {
|
||||
if(inbuf[n] == '\n') {
|
||||
QCString cs(inbuf.data(), n+1);
|
||||
char *p = inbuf.data();
|
||||
++n;
|
||||
int x = inbuf.size() - n;
|
||||
memmove(p, p + n, x);
|
||||
inbuf.resize(x);
|
||||
list += QString::fromUtf8(cs);
|
||||
// start over, basically
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
|
||||
for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
|
||||
handleLine(*it);
|
||||
}
|
||||
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", line.latin1());
|
||||
if(mode == 0) {
|
||||
// first line is the method list
|
||||
QStringList mechlist = QStringList::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) {
|
||||
QString 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") {
|
||||
QCString cs = rest.latin1();
|
||||
QByteArray 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 QString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", line.latin1());
|
||||
QString s = line + '\n';
|
||||
QCString cs = s.latin1();
|
||||
if(mode == 2) {
|
||||
QByteArray 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 QString &_str, int _port) : QServerSocket(_port), port(_port)
|
||||
{
|
||||
sock = 0;
|
||||
sasl = 0;
|
||||
realm = QString::null;
|
||||
str = _str;
|
||||
}
|
||||
|
||||
~ServerTest()
|
||||
{
|
||||
delete sock;
|
||||
delete sasl;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if(!ok()) {
|
||||
printf("Error binding to port %d!\n", port);
|
||||
QTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
char myhostname[256];
|
||||
int r = gethostname(myhostname, sizeof(myhostname)-1);
|
||||
if(r == -1) {
|
||||
printf("Error getting hostname!\n");
|
||||
QTimer::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) {
|
||||
QSocket tmp;
|
||||
tmp.setSocket(s);
|
||||
printf("Connection ignored, already have one active.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Connection received! Starting SASL handshake...\n");
|
||||
|
||||
sock = new QSocket;
|
||||
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 QString &, const QString &)), SLOT(sasl_authCheck(const QString &, const QString &)));
|
||||
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
|
||||
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
|
||||
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
|
||||
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
|
||||
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
|
||||
|
||||
sock->setSocket(s);
|
||||
mode = 0;
|
||||
inbuf.resize(0);
|
||||
|
||||
sasl->setMinimumSSF(0);
|
||||
sasl->setMaximumSSF(256);
|
||||
|
||||
QStringList mechlist;
|
||||
if(!sasl->startServer(PROTO_NAME, host, realm, &mechlist)) {
|
||||
printf("Error starting server!\n");
|
||||
quit();
|
||||
}
|
||||
QString str;
|
||||
bool first = true;
|
||||
for(QStringList::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)
|
||||
{
|
||||
QString s;
|
||||
if(x == QSocket::ErrConnectionRefused)
|
||||
s = "connection refused or timed out";
|
||||
else if(x == QSocket::ErrHostNotFound)
|
||||
s = "host not found";
|
||||
else if(x == QSocket::ErrSocketRead)
|
||||
s = "read error";
|
||||
|
||||
printf("Socket error: %s\n", s.latin1());
|
||||
close();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(sock->canReadLine()) {
|
||||
QString 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 QByteArray &stepData)
|
||||
{
|
||||
QCString cs(stepData.data(), stepData.size()+1);
|
||||
QString line = "C";
|
||||
if(!stepData.isEmpty()) {
|
||||
line += ',';
|
||||
line += cs;
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_authCheck(const QString &user, const QString &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()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
int oldsize = inbuf.size();
|
||||
inbuf.resize(oldsize + a.size());
|
||||
memcpy(inbuf.data() + oldsize, a.data(), a.size());
|
||||
processInbuf();
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray 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:
|
||||
QSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
QString host, realm;
|
||||
int port;
|
||||
int mode;
|
||||
QString str;
|
||||
QByteArray inbuf;
|
||||
int toWrite;
|
||||
|
||||
void processInbuf()
|
||||
{
|
||||
}
|
||||
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", line.latin1());
|
||||
if(mode == 0) {
|
||||
int n = line.find(' ');
|
||||
if(n != -1) {
|
||||
QString mech = line.mid(0, n);
|
||||
QCString cs = line.mid(n+1).latin1();
|
||||
QByteArray clientInit(cs.length());
|
||||
memcpy(clientInit.data(), cs.data(), clientInit.size());
|
||||
sasl->putServerFirstStep(mech, clientInit);
|
||||
}
|
||||
else
|
||||
sasl->putServerFirstStep(line);
|
||||
++mode;
|
||||
}
|
||||
else if(mode == 1) {
|
||||
QString 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") {
|
||||
QCString cs = rest.latin1();
|
||||
QByteArray 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 QString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", line.latin1());
|
||||
QString s = line + '\n';
|
||||
QCString cs = s.latin1();
|
||||
if(mode == 2) {
|
||||
QByteArray 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)
|
||||
{
|
||||
QApplication app(argc, argv, false);
|
||||
|
||||
QString host, user, pass;
|
||||
QString str = "Hello, World";
|
||||
bool server;
|
||||
if(argc < 2) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
QString 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);
|
||||
QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start();
|
||||
app.exec();
|
||||
delete s;
|
||||
}
|
||||
else {
|
||||
ClientTest *c = new ClientTest;
|
||||
QObject::connect(c, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
c->start(host, PROTO_PORT, user, pass);
|
||||
app.exec();
|
||||
delete c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
8
examples/sasltest/sasltest.pro
Normal file
8
examples/sasltest/sasltest.pro
Normal file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = sasltest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp sasltest.cpp
|
||||
include(../examples.pri)
|
221
examples/sslservtest/sslservtest.cpp
Normal file
221
examples/sslservtest/sslservtest.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include<qapplication.h>
|
||||
#include<qfile.h>
|
||||
#include<qsocket.h>
|
||||
#include<qserversocket.h>
|
||||
#include<qtimer.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 SecureServerTest : public QServerSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SecureServerTest(int _port) : QServerSocket(_port), port(_port)
|
||||
{
|
||||
sock = new QSocket;
|
||||
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()), SLOT(ssl_readyReadOutgoing()));
|
||||
connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
|
||||
|
||||
cert.fromPEM(pemdata_cert);
|
||||
privkey.fromPEM(pemdata_privkey);
|
||||
|
||||
fin_mode = 0;
|
||||
}
|
||||
|
||||
~SecureServerTest()
|
||||
{
|
||||
delete ssl;
|
||||
delete sock;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if(cert.isNull() || privkey.isNull()) {
|
||||
printf("Error loading cert and/or private key!\n");
|
||||
QTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
if(!ok()) {
|
||||
printf("Error binding to port %d!\n", port);
|
||||
QTimer::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()) {
|
||||
QSocket tmp;
|
||||
tmp.setSocket(s);
|
||||
printf("throwing away extra connection\n");
|
||||
return;
|
||||
}
|
||||
sock->setSocket(s);
|
||||
printf("Connection received! Starting TLS handshake...\n");
|
||||
ssl->setCertificate(cert, privkey);
|
||||
ssl->startServer();
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_readyRead()
|
||||
{
|
||||
QByteArray 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(fin_mode == 2) {
|
||||
fin_bytes -= x;
|
||||
// last of the bytes written that we care about?
|
||||
if(fin_bytes == 0) {
|
||||
printf("Closing.\n");
|
||||
sock->close();
|
||||
fin_mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sock_error(int)
|
||||
{
|
||||
printf("Socket error.\n");
|
||||
}
|
||||
|
||||
void ssl_handshaken()
|
||||
{
|
||||
printf("Successful SSL handshake. Waiting for newline.\n");
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
QByteArray a = ssl->read();
|
||||
QString str =
|
||||
"<html>\n"
|
||||
"<head><title>Test</title></head>\n"
|
||||
"<body>this is only a test</body>\n"
|
||||
"</html>\n";
|
||||
QCString cs = str.latin1();
|
||||
QByteArray b(cs.length());
|
||||
memcpy(b.data(), cs.data(), b.size());
|
||||
|
||||
printf("Sending test response...\n");
|
||||
fin_mode = 1; // we want to shut down after this block is written
|
||||
ssl->write(b);
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray a = ssl->readOutgoing();
|
||||
|
||||
// The readyReadOutgoing signal following a write will have ALL written data encrypted,
|
||||
// so to ensure data is sent, just ensure the whole encrypted data is sent.
|
||||
if(fin_mode == 1) {
|
||||
fin_bytes = a.size(); // we want to make sure all of it is sent
|
||||
fin_mode = 2;
|
||||
}
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
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;
|
||||
QSocket *sock;
|
||||
QCA::TLS *ssl;
|
||||
QCA::Cert cert;
|
||||
QCA::RSAKey privkey;
|
||||
|
||||
int fin_mode;
|
||||
int fin_bytes;
|
||||
};
|
||||
|
||||
#include"sslservtest.moc"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv, false);
|
||||
int port = argc > 1 ? QString(argv[1]).toInt() : 8000;
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_TLS)) {
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureServerTest *s = new SecureServerTest(port);
|
||||
QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start();
|
||||
app.exec();
|
||||
delete s;
|
||||
|
||||
return 0;
|
||||
}
|
6
examples/sslservtest/sslservtest.pro
Normal file
6
examples/sslservtest/sslservtest.pro
Normal file
@ -0,0 +1,6 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = sslservtest
|
||||
|
||||
SOURCES += sslservtest.cpp
|
||||
include(../examples.pri)
|
270
examples/ssltest/ssltest.cpp
Normal file
270
examples/ssltest/ssltest.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
#include<qapplication.h>
|
||||
#include<qdom.h>
|
||||
#include<qfile.h>
|
||||
#include<qsocket.h>
|
||||
#include<qptrlist.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
QCA::Cert readCertXml(const QDomElement &e)
|
||||
{
|
||||
QCA::Cert cert;
|
||||
// there should be one child data tag
|
||||
QDomElement data = e.elementsByTagName("data").item(0).toElement();
|
||||
if(!data.isNull())
|
||||
cert.fromDER(Base64::stringToArray(data.text()));
|
||||
return cert;
|
||||
}
|
||||
|
||||
void showCertInfo(const QCA::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());
|
||||
}
|
||||
|
||||
QPtrList<QCA::Cert> getRootCerts(const QString &store)
|
||||
{
|
||||
QPtrList<QCA::Cert> list;
|
||||
|
||||
// open the Psi rootcerts file
|
||||
QFile f(store);
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("unable to open %s\n", f.name().latin1());
|
||||
return list;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(&f);
|
||||
f.close();
|
||||
|
||||
QDomElement base = doc.documentElement();
|
||||
if(base.tagName() != "store") {
|
||||
printf("wrong format of %s\n", f.name().latin1());
|
||||
return list;
|
||||
}
|
||||
QDomNodeList 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) {
|
||||
QCA::Cert *cert = new QCA::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;
|
||||
}
|
||||
|
||||
QString resultToString(int result)
|
||||
{
|
||||
QString s;
|
||||
switch(result) {
|
||||
case QCA::TLS::NoCert:
|
||||
s = QObject::tr("No certificate presented.");
|
||||
break;
|
||||
case QCA::TLS::Valid:
|
||||
break;
|
||||
case QCA::TLS::HostMismatch:
|
||||
s = QObject::tr("Hostname mismatch.");
|
||||
break;
|
||||
case QCA::TLS::Rejected:
|
||||
s = QObject::tr("Root CA rejects the specified purpose.");
|
||||
break;
|
||||
case QCA::TLS::Untrusted:
|
||||
s = QObject::tr("Not trusted for the specified purpose.");
|
||||
break;
|
||||
case QCA::TLS::SignatureFailed:
|
||||
s = QObject::tr("Invalid signature.");
|
||||
break;
|
||||
case QCA::TLS::InvalidCA:
|
||||
s = QObject::tr("Invalid CA certificate.");
|
||||
break;
|
||||
case QCA::TLS::InvalidPurpose:
|
||||
s = QObject::tr("Invalid certificate purpose.");
|
||||
break;
|
||||
case QCA::TLS::SelfSigned:
|
||||
s = QObject::tr("Certificate is self-signed.");
|
||||
break;
|
||||
case QCA::TLS::Revoked:
|
||||
s = QObject::tr("Certificate has been revoked.");
|
||||
break;
|
||||
case QCA::TLS::PathLengthExceeded:
|
||||
s = QObject::tr("Maximum cert chain length exceeded.");
|
||||
break;
|
||||
case QCA::TLS::Expired:
|
||||
s = QObject::tr("Certificate has expired.");
|
||||
break;
|
||||
case QCA::TLS::Unknown:
|
||||
default:
|
||||
s = QObject::tr("General validation error.");
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
class SecureTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SecureTest()
|
||||
{
|
||||
sock = new QSocket;
|
||||
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 QCA::TLS;
|
||||
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
|
||||
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
|
||||
connect(ssl, SIGNAL(readyReadOutgoing()), SLOT(ssl_readyReadOutgoing()));
|
||||
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 QString &_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()
|
||||
{
|
||||
QByteArray 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 == QCA::TLS::Valid)
|
||||
printf("Valid certificate.\n");
|
||||
else
|
||||
printf("Invalid certificate: %s\n", resultToString(vr).latin1());
|
||||
|
||||
printf("Let's try a GET request now.\n");
|
||||
QString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
|
||||
QCString cs = req.latin1();
|
||||
QByteArray buf(cs.length());
|
||||
memcpy(buf.data(), cs.data(), buf.size());
|
||||
ssl->write(buf);
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
QByteArray a = ssl->read();
|
||||
QCString cs;
|
||||
cs.resize(a.size()+1);
|
||||
memcpy(cs.data(), a.data(), a.size());
|
||||
printf("%s", cs.data());
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray a = ssl->readOutgoing();
|
||||
sock->writeBlock(a.data(), a.size());
|
||||
}
|
||||
|
||||
void ssl_error(int x)
|
||||
{
|
||||
if(x == QCA::TLS::ErrHandshake) {
|
||||
printf("SSL Handshake Error!\n");
|
||||
quit();
|
||||
}
|
||||
else {
|
||||
printf("SSL Error!\n");
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString host;
|
||||
QSocket *sock;
|
||||
QCA::TLS *ssl;
|
||||
QCA::Cert cert;
|
||||
QPtrList<QCA::Cert> rootCerts;
|
||||
};
|
||||
|
||||
#include"ssltest.moc"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv, false);
|
||||
QString host = argc > 1 ? argv[1] : "andbit.net";
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_TLS)) {
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureTest *s = new SecureTest;
|
||||
QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start(host);
|
||||
app.exec();
|
||||
delete s;
|
||||
|
||||
return 0;
|
||||
}
|
8
examples/ssltest/ssltest.pro
Normal file
8
examples/ssltest/ssltest.pro
Normal file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = ssltest
|
||||
|
||||
INCLUDEPATH += ../common
|
||||
HEADERS += ../common/base64.h
|
||||
SOURCES += ../common/base64.cpp ssltest.cpp
|
||||
include(../examples.pri)
|
Loading…
x
Reference in New Issue
Block a user