23#include <QCoreApplication>
33#include "import_plugins.h"
38 printf(
"* %s ", qPrintable(s));
41 fgets(line, 255, stdin);
53 s = QStringLiteral(
"connection refused or timed out");
56 s = QStringLiteral(
"remote host closed the connection");
59 s = QStringLiteral(
"host not found");
62 s = QStringLiteral(
"access error");
65 s = QStringLiteral(
"too many sockets");
68 s = QStringLiteral(
"operation timed out");
71 s = QStringLiteral(
"datagram was larger than system limit");
74 s = QStringLiteral(
"network error");
77 s = QStringLiteral(
"address is already in use");
80 s = QStringLiteral(
"address does not belong to the host");
83 s = QStringLiteral(
"operation is not supported by the local operating system");
86 s = QStringLiteral(
"unknown socket error");
97 s = QStringLiteral(
"no appropriate mechanism could be negotiated");
100 s = QStringLiteral(
"bad SASL protocol");
103 s = QStringLiteral(
"server failed mutual authentication");
107 s = QStringLiteral(
"generic authentication failure");
113class ClientTest :
public QObject
118 QString host, proto, authzid, realm, user, pass;
120 bool no_authzid, no_realm;
129 ClientTest(
const QString &_host,
131 const QString &_proto,
132 const QString &_authzid,
133 const QString &_realm,
134 const QString &_user,
135 const QString &_pass,
145 , no_authzid(_no_authzid)
146 , no_realm(_no_realm)
150 sock =
new QTcpSocket(
this);
153#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
159 sasl =
new QCA::SASL(
this);
175 flags |= QCA::SASL::AllowPlain;
176 flags |= QCA::SASL::AllowAnonymous;
180 sasl->setUsername(user);
181 if (!authzid.isEmpty())
182 sasl->setAuthzid(authzid);
184 sasl->setPassword(pass.toUtf8());
185 if (!realm.isEmpty())
186 sasl->setRealm(realm);
188 printf(
"Connecting to %s:%d, for protocol %s\n", qPrintable(host), port, qPrintable(proto));
189 sock->connectToHost(host, port);
196 void sock_connected()
198 printf(
"Connected to server. Awaiting mechanism list...\n");
211 printf(
"Error: server closed connection unexpectedly.\n");
217 printf(
"Error: socket: %s\n", qPrintable(socketErrorToString(x)));
221 void sock_readyRead()
225 QByteArray a = sock->readAll();
226 printf(
"Read %d bytes\n",
int(a.
size()));
251 if (waitCycles == 0) {
256 sasl->writeIncoming(a);
259 if (sock->canReadLine()) {
267 void sasl_clientFirstStep(
bool clientInit,
const QByteArray &clientInitData)
269 printf(
"Choosing mech: %s\n", qPrintable(sasl->mechanism()));
270 QString line = sasl->mechanism();
272 line += QLatin1Char(
' ');
273 line += arrayToString(clientInitData);
278 void sasl_nextStep(
const QByteArray &stepData)
280 QString line = QStringLiteral(
"C");
282 line += QLatin1Char(
',');
283 line += arrayToString(stepData);
288 void sasl_needParams(
const QCA::SASL::Params ¶ms)
291 user = prompt(QStringLiteral(
"Username:"));
292 sasl->setUsername(user);
296 authzid = prompt(QStringLiteral(
"Authorize As (enter to skip):"));
297 if (!authzid.isEmpty())
298 sasl->setAuthzid(authzid);
302 QCA::ConsolePrompt prompt;
303 prompt.getHidden(QStringLiteral(
"* Password"));
304 prompt.waitForFinished();
305 QCA::SecureArray pass = prompt.result();
306 sasl->setPassword(pass);
310 QStringList realms = sasl->realmList();
311 printf(
"Available realms:\n");
313 printf(
" (none specified)\n");
314 foreach (
const QString &s, realms)
315 printf(
" %s\n", qPrintable(s));
316 realm = prompt(QStringLiteral(
"Realm (enter to skip):"));
317 if (!realm.isEmpty())
318 sasl->setRealm(realm);
321 sasl->continueAfterParams();
324 void sasl_authenticated()
326 printf(
"SASL success!\n");
327 printf(
"SSF: %d\n", sasl->ssf());
330 void sasl_readyRead()
332 QByteArray a = sasl->read();
337 void sasl_readyReadOutgoing()
339 QByteArray a = sasl->readOutgoing();
345 int e = sasl->errorCode();
347 printf(
"Error: sasl: initialization failed.\n");
349 printf(
"Error: sasl: %s.\n", qPrintable(saslAuthConditionToString(sasl->authCondition())));
351 printf(
"Error: sasl: broken security layer.\n");
353 printf(
"Error: sasl: unknown error.\n");
358 void waitWriteIncoming()
361 if (waitCycles > 0) {
372 if (sock_done && waitCycles == 0) {
373 printf(
"Finished, server closed connection.\n");
385 sasl->disconnect(
this);
391 QString arrayToString(
const QByteArray &ba)
393 return QCA::Base64().arrayToString(ba);
396 QByteArray stringToArray(
const QString &s)
398 return QCA::Base64().stringToArray(s).toByteArray();
401 void sendLine(
const QString &line)
403 printf(
"Writing: {%s}\n", qPrintable(line));
404 QString s = line + QLatin1Char(
'\n');
405 QByteArray a = s.
toUtf8();
417 while ((at = inbuf.indexOf(
'\n')) != -1) {
419 inbuf = inbuf.mid(at + 1);
423 foreach (
const QString &line, list)
427 void handleLine(
const QString &line)
429 printf(
"Reading: [%s]\n", qPrintable(line));
432 const QStringList mechlist = line.
split(QLatin1Char(
' '));
434 sasl->startClient(proto, host, mechlist);
435 }
else if (mode == 1) {
437 int n = line.
indexOf(QLatin1Char(
','));
440 rest = line.
mid(n + 1);
444 if (type == QLatin1String(
"C")) {
445 sasl->putStep(stringToArray(rest));
446 }
else if (type == QLatin1String(
"E")) {
448 printf(
"Error: server says: %s.\n", qPrintable(rest));
450 printf(
"Error: server error, unspecified.\n");
453 }
else if (type == QLatin1String(
"A")) {
454 printf(
"Authentication success.\n");
463 printf(
"Error: Bad format from peer, closing.\n");
473 printf(
"usage: saslclient (options) host(:port) (user) (pass)\n");
474 printf(
"options: --proto=x, --authzid=x, --realm=x\n");
477int main(
int argc,
char **argv)
486 QString proto = QStringLiteral(
"qcatest");
488 bool no_authzid =
false;
489 bool no_realm =
false;
490 for (
int n = 0; n < args.
count(); ++n) {
498 var = opt.
mid(0, at);
499 val = opt.
mid(at + 1);
523 if (args.
count() < 1) {
532 if (args.
count() >= 2)
534 if (args.
count() >= 3)
539 host = hostinput.
mid(0, at);
540#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
543 port = hostinput.midRef(at + 1).
toInt();
549 printf(
"Error: SASL support not found.\n");
553 ClientTest client(host, port, proto, authzid, realm, user, pass, no_authzid, no_realm);
561#include "saslclient.moc"
Convenience method for initialising and cleaning up QCA.
bool needPassword() const
Password is needed.
bool canSendAuthzid() const
An Authorization ID can be sent if desired.
bool needUsername() const
User is needed.
bool canSendRealm() const
A Realm can be sent if desired.
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.
@ BadProtocol
Bad protocol or cancelled.
@ NoMechanism
No compatible/appropriate authentication mechanism.
@ BadServer
Server failed mutual authentication (client side only)
void clientStarted(bool clientInit, const QByteArray &clientInitData)
This signal is emitted when the client has been successfully started.
void needParams(const QCA::SASL::Params ¶ms)
This signal is emitted when the client needs additional parameters.
@ 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.
Type type(const QSqlDatabase &db)
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QCA_EXPORT bool isSupported(const char *features, const QString &provider=QString())
Test if a capability (algorithm) is available.
SocketError error() const const
void errorOccurred(QAbstractSocket::SocketError socketError)
bool isEmpty() const const
qsizetype size() const const
qsizetype count() const const
bool isEmpty() 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)
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) 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