Exemple #1
0
	int clientTryAgain()
	{
		if(step == 0) {
			out_mech = "DIGEST-MD5";
			++step;
			return Continue;
		}
		else if(step == 1) {
			// if we still need params, then the app has failed us!
			if(need.user || need.authzid || need.pass || need.realm) {
				err = -1;
				return Error;
			}

			// see if some params are needed
			if(!have.user)
				need.user = true;
			if(!have.authzid)
				need.authzid = true;
			if(!have.pass)
				need.pass = true;
			if(need.user || need.authzid || need.pass)
				return NeedParams;

			// get props
			QByteArray cs(in_buf.data(), in_buf.size());
			PropList in;
			if(!in.fromString(cs)) {
				err = QCA::SASL::BadProto;
				return Error;
			}

			// make a cnonce
			QByteArray a(32, 0);
			for(int n = 0; n < (int)a.size(); ++n)
				a[n] = (char)(256.0*rand()/(RAND_MAX+1.0));
			QByteArray cnonce = Base64::arrayToString(a).toLatin1();

			// make other variables
			realm = host;
			QByteArray nonce = in.get("nonce");
			QByteArray nc = "00000001";
			QByteArray uri = service.toUtf8() + '/' + host.toUtf8();
			QByteArray qop = "auth";

			// build 'response'
			QByteArray X = user.toUtf8() + ':' + realm.toUtf8() + ':' + pass.toUtf8();
			QByteArray Y = QCA::MD5::hash(X);
			QByteArray tmp = QByteArray(":") + nonce + ':' + cnonce + ':' + authz.toUtf8();
			QByteArray A1(Y.size() + tmp.length(), 0);
			memcpy(A1.data(), Y.data(), Y.size());
			memcpy(A1.data() + Y.size(), tmp.data(), tmp.length());
			QByteArray A2 = "AUTHENTICATE:" + uri;
			QByteArray HA1 = QCA::MD5::hashToString(A1).toLatin1();
			QByteArray HA2 = QCA::MD5::hashToString(A2).toLatin1();
			QByteArray KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2;
			QByteArray Z = QCA::MD5::hashToString(KD).toLatin1();

			// build output
			PropList out;
			out.set("username", user.toUtf8());
			out.set("realm", host.toUtf8());
			out.set("nonce", nonce);
			out.set("cnonce", cnonce);
			out.set("nc", nc);
			out.set("serv-type", service.toUtf8());
			out.set("host", host.toUtf8());
			out.set("digest-uri", uri);
			out.set("qop", qop);
			out.set("response", Z);
			out.set("charset", "utf-8");
			out.set("authzid", authz.toUtf8());
			QByteArray s = out.toString();

			// done
			//out_buf.resize(s.length());
			//memcpy(out_buf.data(), s.data(), out_buf.size());
			out_buf = s;
			++step;
			return Continue;
		}
		else {
			out_buf.resize(0);
			return Success;
		}
	}
    virtual void tryAgain() {
        // All exits of the method must emit the ready signal
        // so all exits go through a goto ready;
        if(step == 0) {
            out_mech = mechanism_;

#ifdef SIMPLESASL_PLAIN
            // PLAIN
            if (out_mech == "PLAIN") {
                // First, check if we have everything
                if(need.user || need.pass) {
                    qWarning("simplesasl.cpp: Did not receive necessary auth parameters");
                    result_ = Error;
                    goto ready;
                }
                if(!have.user)
                    need.user = true;
                if(!have.pass)
                    need.pass = true;
                if(need.user || need.pass) {
                    result_ = Params;
                    goto ready;
                }

                // Continue with authentication
                QByteArray plain;
                if (!authz.isEmpty())
                    plain += authz.toUtf8();
                plain += '\0' + user.toUtf8() + '\0' + pass.toByteArray();
                out_buf.resize(plain.length());
                memcpy(out_buf.data(), plain.data(), out_buf.size());
            }
#endif
            ++step;
            if (out_mech == "PLAIN")
                result_ = Success;
            else
                result_ = Continue;
        }
        else if(step == 1) {
            // if we still need params, then the app has failed us!
            if(need.user || need.authzid || need.pass || need.realm) {
                qWarning("simplesasl.cpp: Did not receive necessary auth parameters");
                result_ = Error;
                goto ready;
            }
            // see if some params are needed
            if(!have.user)
                need.user = true;
            //if(!have.authzid)
            //	need.authzid = true;
            if(!have.pass)
                need.pass = true;
            if(need.user || need.authzid || need.pass) {
                result_ = Params;
                goto ready;
            }

            // get props
            QByteArray cs(in_buf);
            PropList in;
            if(!in.fromString(cs)) {
                authCondition_ = QCA::SASL::BadProtocol;
                result_ = Error;
                goto ready;
            }
            //qDebug() << (QString("simplesasl.cpp: IN: %1").arg(QString(in.toString())));

            // make a cnonce
            QByteArray a(32,'\0');
            for(int n = 0; n < (int)a.size(); ++n)
                a[n] = (char)(256.0*rand()/(RAND_MAX+1.0));
            QByteArray cnonce = QCA::Base64().arrayToString(a).toLatin1();

            // make other variables
            if (realm.isEmpty())
                realm = QString::fromUtf8(in.get("realm"));
            QByteArray nonce = in.get("nonce");
            QByteArray nc = "00000001";
            QByteArray uri = service.toUtf8() + '/' + host.toUtf8();
            QByteArray qop = "auth";

            // build 'response'
            QByteArray X = user.toUtf8() + ':' + realm.toUtf8() + ':' + pass.toByteArray();
            QByteArray Y = QCA::Hash("md5").hash(X).toByteArray();
            QByteArray tmp = ':' + nonce + ':' + cnonce;
            if (!authz.isEmpty())
                tmp += ':' + authz.toUtf8();
            //qDebug() << (QString(tmp));

            QByteArray A1(Y + tmp);
            QByteArray A2 = QByteArray("AUTHENTICATE:") + uri;
            QByteArray HA1 = QCA::Hash("md5").hashToString(A1).toLatin1();
            QByteArray HA2 = QCA::Hash("md5").hashToString(A2).toLatin1();
            QByteArray KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2;
            QByteArray Z = QCA::Hash("md5").hashToString(KD).toLatin1();

            //qDebug() << (QString("simplesasl.cpp: A1 = %1").arg(QString(A1)).toAscii());
            //qDebug() << (QString("simplesasl.cpp: A2 = %1").arg(QString(A2)).toAscii());
            //qDebug() << (QString("simplesasl.cpp: KD = %1").arg(QString(KD)).toAscii());

            // build output
            PropList out;
            out.set("username", user.toUtf8());
            if (!realm.isEmpty())
                out.set("realm", realm.toUtf8());
            out.set("nonce", nonce);
            out.set("cnonce", cnonce);
            out.set("nc", nc);
            //out.set("serv-type", service.utf8());
            //out.set("host", host.utf8());
            out.set("digest-uri", uri);
            out.set("qop", qop);
            out.set("response", Z);
            out.set("charset", "utf-8");
            if (!authz.isEmpty())
                out.set("authzid", authz.toUtf8());
            QByteArray s(out.toString());
            //qDebug() << (QString("OUT: %1").arg(QString(out.toString())));

            // done
            out_buf.resize(s.length());
            memcpy(out_buf.data(), s.data(), out_buf.size());
            ++step;
            result_ = Continue;
        }
        /*		else if (step == 2) {
        			out_buf.resize(0);
        			result_ = Continue;
        			++step;
        		}*/
        else {
            out_buf.resize(0);
            result_ = Success;
        }
ready:
        QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection);
    }