| Home |
This example demonstrates how to use QtSSLSocket to create a simple secure SSL server.
sslserver.h:
/****************************************************************************
**
** Copyright (C) 2003-2006 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding valid Qt Solutions licenses may use this file in
** accordance with the Qt Solutions License Agreement provided with the
** Software.
**
** See http://www.trolltech.com/products/qt/addon/solutions/
** or email [email protected] for information about Qt Solutions
** License Agreements.
**
** Contact [email protected] if any conditions of this licensing are
** not clear to you.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#ifndef SSLSERVER_H
#define SSLSERVER_H
#include <qtcpserver.h>
class QtSslSocket;
class SSLServerConnection : public QObject
{
Q_OBJECT
public:
SSLServerConnection(quint16 socket, QObject *parent = 0);
~SSLServerConnection();
public slots:
void acceptedClient();
void readData();
void connectionClosed();
void error(QAbstractSocket::SocketError err);
private:
unsigned int readBytes;
unsigned int writtenBytes;
QtSslSocket *socket;
};
class SSLServer : public QTcpServer
{
Q_OBJECT
public:
SSLServer(quint16 port, QObject *parent = 0);
void incomingConnection(int socket);
};
#endif
sslserver.cpp:
/****************************************************************************
**
** Copyright (C) 2003-2006 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding valid Qt Solutions licenses may use this file in
** accordance with the Qt Solutions License Agreement provided with the
** Software.
**
** See http://www.trolltech.com/products/qt/addon/solutions/
** or email [email protected] for information about Qt Solutions
** License Agreements.
**
** Contact [email protected] if any conditions of this licensing are
** not clear to you.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "sslserver.h"
#include <qdir.h>
#include <qfileinfo.h>
#include <qdatetime.h>
#include <qtsslsocket.h>
SSLServer::SSLServer(quint16 port, QObject *parent)
: QTcpServer(parent)
{
listen(QHostAddress::Any, port);
}
void SSLServer::incomingConnection(int socket)
{
// As soon as a client connects, pass its incoming socket id to a
// SSLServerConnection child. This child is deleted after the
// connection is closed (see the connectionClosed() slot).
new SSLServerConnection(socket, this);
}
SSLServerConnection::SSLServerConnection(quint16 socketDescriptor,
QObject *parent)
: QObject(parent)
{
// Create an SSL socket and make its QTcpSocket use our accepted
// socket, then give it the path to our certificate & private key
// file. For notes on this file, please check the provided
// "server.txt".
socket = new QtSslSocket(QtSslSocket::Server, this);
socket->socket()->setSocketDescriptor(socketDescriptor);
socket->setPathToCertificate("sslserver.pem");
socket->setPathToPrivateKey("sslserver.pem");
// Notice the platform dependency here; the location of the CA
// certificate bundle is specific to the OS.
socket->setPathToCACertDir("/etc/ssl/certs");
// Connect the SSL socket's signals to our slots.
connect(socket, SIGNAL(connected()), SLOT(acceptedClient()));
connect(socket, SIGNAL(disconnected()), SLOT(connectionClosed()));
connect(socket, SIGNAL(readyRead()), SLOT(readData()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(error(QAbstractSocket::SocketError)));
// Call sslAccepted(). After this, when the SSL socket emits
// accepted(), we are ready to go. We ignore the return value of
// this function, because it will always fail the first time we
// call it.
socket->sslAccept();
}
SSLServerConnection::~SSLServerConnection()
{
// Report that the connection has closed.
qDebug("Connection closed.");
}
void SSLServerConnection::acceptedClient()
{
// Provide feedback to the user about incoming connections. This
// slot is only called if the connection was established, so all
// communication is now encrypted.
qDebug("Accepted new client from %s:%d",
qPrintable(socket->peerAddress().toString()),
socket->peerPort());
// Print a simple DOS-like prompt. Write this to the SSL socket.
// The SSL socket encrypts the data, and sends it to the client.
QString s = "Welcome to Fake-DOS 2.11\r\nC:\\>";
socket->write(s.toLatin1().constData(), s.length());
}
void SSLServerConnection::readData()
{
// First, read all incoming data from the client. The SSL socket
// has already decrypted it for us. We assume that the client uses
// a plain text protocol, so we convert the data to a QString.
QString incoming(socket->readAll());
// This server accepts only the commands "EXIT" and "DIR",
// although case insensitive. All other commands are rejected with
// "bad command or file name". Write response back to the client
// through the SSL socket.
QString command = incoming.toUpper().trimmed();
if (command == "EXIT") {
QString s = "system halted\r\n";
socket->write(s.toLatin1().constData(), s.length());
socket->close();
} else if (command == "DIR") {
QDir cwd(".");
const QFileInfoList cwdlist = cwd.entryInfoList();
if (cwdlist.isEmpty()) {
QString s = "unable to list directory contents\r\nC:\\>";
socket->write(s.toLatin1().constData(), s.length());
} else {
QString s = " Volume in drive C has no label.\r\n";
s += " Volume Serial Number is C564-1226\r\n\r\n";
s += " Directory of C:\\\r\n\r\n";
QListIterator<QFileInfo> it(cwdlist);
int nfiles = 0;
int ndirs = 0;
int tildes = 0;
while (it.hasNext()) {
QFileInfo f = it.next();
QDate d = f.created().date();
QTime t = f.created().time();
QString line;
bool dots = f.fileName() == "." || f.fileName() == "..";
QString fname = dots ? QString("") : f.baseName().toUpper();
QString lname = dots ? f.fileName() : f.completeSuffix().toUpper().left(3);
if (fname.length() > 8) {
QString tmp;
tmp.sprintf("~%i", ++tildes);
fname = fname.left(8 - tmp.length()) + tmp;
}
if (f.isDir()) {
line.sprintf("%8s %3s <DIR> %02i-%02i-%02i %2i:%02i%c\r\n",
qPrintable(fname), qPrintable(lname),
d.day(), d.month(),
(d.year() - 1900) % 100, t.hour() % 12, t.minute(),
t.hour() > 12 ? 'p' : 'a');
} else {
line.sprintf("%8s %3s %7d %02i-%02i-%02i %2i:%02i%c\r\n",
qPrintable(fname), qPrintable(lname),
(int)f.size(), d.day(), d.month(),
(d.year() - 1900) % 100, t.hour() % 12, t.minute(),
t.hour() > 12 ? 'p' : 'a');
}
s += line;
if (f.isDir())
++ndirs;
else
++nfiles;
}
QString line;
line.sprintf("%16i File(s)\r\n", nfiles);
s += line;
line.sprintf("%16i Dir(s)\r\n", ndirs);
s += line;
s += "C:\\>";
socket->write(s.toLatin1().constData(), s.length());
}
} else {
QString s = "bad command or file name\r\nC:\\>";
socket->write(s.toLatin1().constData(), s.length());
}
}
void SSLServerConnection::connectionClosed()
{
// Although the socket may be closing, we must not delete it until
// the delayed close is done.
if (socket->socket()->state() == QAbstractSocket::ClosingState) {
connect(socket->socket(), SIGNAL(disconnected()), SLOT(deleteLater()));
} else {
deleteLater();
return;
}
qDebug("Connection closed.");
}
void SSLServerConnection::error(QAbstractSocket::SocketError)
{
// The SSL socket conveniently provides human readable error
// messages through the errorString() call. Note that sometimes
// the errors come directly from the underlying SSL library, and
// the quality of the text may vary.
qDebug("Error: %s", qPrintable(socket->errorString()));
}
main.cpp:
/****************************************************************************
**
** Copyright (C) 2003-2006 Trolltech ASA. All rights reserved.
**
** This file is part of a Qt Solutions component.
**
** Licensees holding valid Qt Solutions licenses may use this file in
** accordance with the Qt Solutions License Agreement provided with the
** Software.
**
** See http://www.trolltech.com/products/qt/addon/solutions/
** or email [email protected] for information about Qt Solutions
** License Agreements.
**
** Contact [email protected] if any conditions of this licensing are
** not clear to you.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include <qapplication.h>
#include <stdlib.h>
#include <qfileinfo.h>
#include "sslserver.h"
/*
An SSL server that is started from the console.
This example demonstrates the use of the QtSSLSocket class in a
server application.
*/
int main(int argc, char *argv[])
{
QFileInfo cert("sslserver.pem");
if (!cert.exists()) {
qDebug("Note: This server requires the file sslserver.pem to exist, "
"and to contain the SSL private key and certificate for "
"this server, encoded in PEM format. Please read "
"server.txt for more information.");
return 1;
}
if (argc < 2) {
qDebug("usage: %s <port>", argv[0]);
qDebug("A simple SSL server.");
return 1;
}
QApplication app(argc, argv, false);
int port = atoi(argv[1]);
SSLServer sserver(port);
qDebug("Listening on port %i. Please press Ctrl-C to exit.", port);
return app.exec();
}
server.pro:
TEMPLATE = app
INCLUDEPATH += .
CONFIG += console
include(../../src/qtsslsocket.pri)
HEADERS += sslserver.h
SOURCES += main.cpp sslserver.cpp
| Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies) | Trademarks | Qt Solutions |