23#include <QCoreApplication>
33#include "import_plugins.h"
41 s = QStringLiteral(
"connection refused or timed out");
44 s = QStringLiteral(
"remote host closed the connection");
47 s = QStringLiteral(
"host not found");
50 s = QStringLiteral(
"access error");
53 s = QStringLiteral(
"too many sockets");
56 s = QStringLiteral(
"operation timed out");
59 s = QStringLiteral(
"datagram was larger than system limit");
62 s = QStringLiteral(
"network error");
65 s = QStringLiteral(
"address is already in use");
68 s = QStringLiteral(
"address does not belong to the host");
71 s = QStringLiteral(
"operation is not supported by the local operating system");
74 s = QStringLiteral(
"unknown socket error");
85 s = QStringLiteral(
"no appropriate mechanism could be negotiated");
88 s = QStringLiteral(
"bad SASL protocol");
91 s = QStringLiteral(
"authentication failed");
94 s = QStringLiteral(
"authorization failed");
97 s = QStringLiteral(
"mechanism too weak for this user");
100 s = QStringLiteral(
"encryption is needed to use this mechanism");
103 s = QStringLiteral(
"passphrase expired");
106 s = QStringLiteral(
"account is disabled");
109 s = QStringLiteral(
"user not found");
112 s = QStringLiteral(
"needed remote service is unavailable");
116 s = QStringLiteral(
"generic authentication failure");
124class ServerTest :
public QObject
129 QString host, proto, realm, str;
131 QTcpServer *tcpServer;
135 ServerTest(
const QString &_host,
int _port,
const QString &_proto,
const QString &_realm,
const QString &_str);
138 void releaseId(
int id);
147 void server_newConnection();
152class ServerTestHandler :
public QObject
157 ServerTest *serverTest;
161 QString host, proto, realm, str;
166 ServerTestHandler(ServerTest *_serverTest,
168 const QString &_host,
169 const QString &_proto,
170 const QString &_realm,
172 : serverTest(_serverTest)
179 id = serverTest->reserveId();
181 sock->setParent(
this);
184#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
190 &ServerTestHandler::sock_error);
194 sasl =
new QCA::SASL(
this);
207 flags |= QCA::SASL::AllowPlain;
208 flags |= QCA::SASL::AllowAnonymous;
211 printf(
"%d: Connection received! Starting SASL handshake...\n",
id);
212 sasl->startServer(proto, host, realm);
215 ~ServerTestHandler()
override
217 serverTest->releaseId(
id);
221 void sasl_serverStarted()
223 sendLine(sasl->mechanismList().join(QStringLiteral(
" ")));
226 void sock_disconnected()
228 printf(
"%d: Connection closed.\n",
id);
235 printf(
"%d: Error: client closed connection unexpectedly.\n",
id);
240 printf(
"%d: Error: socket: %s\n",
id, qPrintable(socketErrorToString(x)));
244 void sock_readyRead()
246 if (sock->canReadLine()) {
253 void sock_bytesWritten(qint64 x)
257 toWrite -= sasl->convertBytesWritten(x);
259 printf(
"%d: Sent, closing.\n",
id);
265 void sasl_nextStep(
const QByteArray &stepData)
267 QString line = QStringLiteral(
"C");
269 line += QLatin1Char(
',');
270 line += arrayToString(stepData);
275 void sasl_authCheck(
const QString &user,
const QString &authzid)
277 printf(
"%d: AuthCheck: User: [%s], Authzid: [%s]\n",
id, qPrintable(user), qPrintable(authzid));
290 sasl->continueAfterAuthCheck();
293 void sasl_authenticated()
295 sendLine(QStringLiteral(
"A"));
296 printf(
"%d: Authentication success.\n",
id);
298 printf(
"%d: SSF: %d\n",
id, sasl->ssf());
302 void sasl_readyRead()
304 QByteArray a = sasl->read();
305 printf(
"%d: Warning, client sent %d bytes unexpectedly.\n",
id,
int(a.
size()));
308 void sasl_readyReadOutgoing()
310 sock->write(sasl->readOutgoing());
315 int e = sasl->errorCode();
317 printf(
"%d: Error: sasl: initialization failed.\n",
id);
319 QString errstr = saslAuthConditionToString(sasl->authCondition());
320 sendLine(QStringLiteral(
"E,") + errstr);
321 printf(
"%d: Error: sasl: %s.\n",
id, qPrintable(errstr));
323 printf(
"%d: Error: sasl: broken security layer.\n",
id);
325 printf(
"%d: Error: sasl: unknown error.\n",
id);
337 void handleLine(
const QString &line)
339 printf(
"%d: Reading: [%s]\n",
id, qPrintable(line));
341 int n = line.
indexOf(QLatin1Char(
' '));
343 QString mech = line.
mid(0, n);
345 sasl->putServerFirstStep(mech, stringToArray(rest));
347 sasl->putServerFirstStep(line);
349 }
else if (mode == 1) {
351 int n = line.
indexOf(QLatin1Char(
','));
354 rest = line.
mid(n + 1);
357 rest = QLatin1String(
"");
360 if (type == QLatin1String(
"C")) {
361 sasl->putStep(stringToArray(rest));
363 printf(
"%d: Bad format from peer, closing.\n",
id);
370 QString arrayToString(
const QByteArray &ba)
376 QByteArray stringToArray(
const QString &s)
379 return decoder.stringToArray(s).toByteArray();
382 void sendLine(
const QString &line)
384 printf(
"%d: Writing: {%s}\n",
id, qPrintable(line));
385 QString s = line + QLatin1Char(
'\n');
386 QByteArray a = s.
toUtf8();
398ServerTest::ServerTest(
const QString &_host,
413int ServerTest::reserveId()
416 while (ids.contains(n))
422void ServerTest::releaseId(
int id)
427void ServerTest::start()
430 printf(
"Error: unable to bind to port %d.\n", port);
435 printf(
"Serving on %s:%d, for protocol %s ...\n", qPrintable(host), port, qPrintable(proto));
438void ServerTest::server_newConnection()
440 QTcpSocket *sock = tcpServer->nextPendingConnection();
441 new ServerTestHandler(
this, sock, host, proto, realm, str);
448 printf(
"usage: saslserver host (message)\n");
449 printf(
"options: --proto=x, --realm=x\n");
452int main(
int argc,
char **argv)
463 QString proto = QStringLiteral(
"qcatest");
465 for (
int n = 0; n < args.
count(); ++n) {
473 var = opt.
mid(0, at);
474 val = opt.
mid(at + 1);
487 if (args.
count() < 1) {
496 QString str = QStringLiteral(
"Hello, World");
497 if (args.
count() >= 2)
502 host = hostinput.
mid(0, at);
503#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
506 port = hostinput.midRef(at + 1).
toInt();
512 printf(
"Error: SASL support not found.\n");
516 ServerTest server(host, port, proto, realm, str);
524#include "saslserver.moc"
Convenience method for initialising and cleaning up QCA.
void authCheck(const QString &user, const QString &authzid)
This signal is emitted when the server needs to perform the authentication check.
void nextStep(const QByteArray &stepData)
This signal is emitted when there is data required to be sent over the network to complete the next s...
AuthCondition
Possible authentication error states.
@ NeedEncrypt
Encryption is needed in order to use mechanism (server side only)
@ TooWeak
Mechanism too weak for this user (server side only)
@ BadProtocol
Bad protocol or cancelled.
@ NoUser
User not found (server side only)
@ NoMechanism
No compatible/appropriate authentication mechanism.
@ RemoteUnavailable
Remote service needed for auth is gone (server side only)
@ Expired
Passphrase expired, has to be reset (server side only)
@ Disabled
Account is disabled (server side only)
@ BadAuth
Authentication failure (server side only)
@ NoAuthzid
Authorization failure (server side only)
void serverStarted()
This signal is emitted after the server has been successfully started.
@ ErrorInit
problem starting up SASL
@ ErrorCrypt
problem at anytime after
@ ErrorHandshake
problem during the authentication process
void authenticated()
This signal is emitted when authentication is complete.
AuthFlags
Authentication requirement flag values.
void error()
This signal is emitted when an error is detected.
void readyReadOutgoing()
This signal is emitted when SecureLayer has encrypted (network side) data ready to be read.
void readyRead()
This signal is emitted when SecureLayer has decrypted (application side) data ready to be read.
QString arrayToString(const MemoryRegion &a)
Process an array in the "forward" direction, returning a QString.
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QCA_EXPORT bool isSupported(const char *features, const QString &provider=QString())
Test if a capability (algorithm) is available.
@ Decode
Operate in the "reverse" direction; for example, decrypting.
QCA_EXPORT void setAppName(const QString &name)
Set the application name that will be used by SASL server mode.
SocketError error() const const
void errorOccurred(QAbstractSocket::SocketError socketError)
bool isEmpty() const const
qsizetype size() const const
void bytesWritten(qint64 bytes)
qsizetype count() const const
QList< T > mid(qsizetype pos, qsizetype length) const const
void removeAt(qsizetype i)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLatin1(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
int toInt(bool *ok, int base) const const
QByteArray toUtf8() const const
void truncate(qsizetype position)
QStringView mid(qsizetype start, qsizetype length) const const
int toInt(bool *ok, int base) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)