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 |