void TorController::authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n"); std::pair<std::string,std::string> l = SplitTorReplyLine(reply.lines[0]); if (l.first == "AUTHCHALLENGE") { std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); std::vector<uint8_t> serverHash = ParseHex(m["SERVERHASH"]); std::vector<uint8_t> serverNonce = ParseHex(m["SERVERNONCE"]); LogPrint("tor", "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); if (serverNonce.size() != 32) { LogPrintf("tor: ServerNonce is not 32 bytes, as required by spec\n"); return; } std::vector<uint8_t> computedServerHash = ComputeResponse(TOR_SAFE_SERVERKEY, cookie, clientNonce, serverNonce); if (computedServerHash != serverHash) { LogPrintf("tor: ServerHash %s does not match expected ServerHash %s\n", HexStr(serverHash), HexStr(computedServerHash)); return; } std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); } } else { LogPrintf("tor: SAFECOOKIE authentication challenge failed\n"); } }
//test for collisions and report the results. Also provide a //simple collision response to colliding objects. void CollisionTestReportAndRespond(void) { VCReport report; vc.Collide( &report ); //perform collision test. //default is VC_FIRST_CONTACT int j; for (j = 0; j < report.numObjPairs(); j++) { std::cout << "Detected collision between objects " << report.obj1ID(j) <<" and "<< report.obj2ID(j) <<"\n"; polyObject *p1 = GetObjectWithId(report.obj1ID(j)); polyObject *p2 = GetObjectWithId(report.obj2ID(j)); Vector normal; normal = p1->position - p2->position; normal.normalize(); ComputeResponse(normal, (p1->v), &(p1->v) ); normal = p2->position - p1->position; normal.normalize(); ComputeResponse(normal, (p2->v), &(p2->v) ); } SinkAndSource(); }
bool PluginAuth::FullAuth(XmppHandler * xmpp, QByteArray const& data, Bunny ** pBunny, QByteArray & answer) { switch(xmpp->currentAuthStep) { case 0: // We should receive <?xml version='1.0' encoding='UTF-8'?><stream:stream to='ojn.soete.org' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>" if(data.startsWith("<?xml version='1.0' encoding='UTF-8'?>")) { // Send an auth Request answer.append("<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='2173750751' from='xmpp.nabaztag.com' version='1.0' xml:lang='en'>"); answer.append("<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism></mechanisms><register xmlns='http://violet.net/features/violet-register'/></stream:features>"); xmpp->currentAuthStep = 1; return true; } LogError("Bad Auth Step 0, disconnect"); return false; case 1: { // Bunny request a register <iq type='get' id='1'><query xmlns='violet:iq:register'/></iq> IQ iq(data); if(iq.IsValid() && iq.Type() == IQ::Iq_Get && iq.Content() == "<query xmlns='violet:iq:register'/>") { // Send the request answer = iq.Reply(IQ::Iq_Result, "from='" + xmpp->GetXmppDomain() + "' %1 %4", "<query xmlns='violet:iq:register'><instructions>Choose a username and password to register with this server</instructions><username/><password/></query>"); xmpp->currentAuthStep = 100; return true; } // Bunny request an auth <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/> if(data.startsWith("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>")) { // Send a challenge // <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>...</challenge> // <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>nonce="random_number",qop="auth",charset=utf-8,algorithm=md5-sess</challenge> QByteArray nonce = QByteArray::number((unsigned int)qrand()); QByteArray challenge = "nonce=\"" + nonce + "\",qop=\"auth\",charset=utf-8,algorithm=md5-sess"; answer.append("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + challenge.toBase64() + "</challenge>"); xmpp->currentAuthStep = 2; return true; } LogError("Bad Auth Step 1, disconnect"); return false; } case 2: { // We should receive <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>...</response> QRegExp rx("<response[^>]*>(.*)</response>"); if (rx.indexIn(data) != -1) { QByteArray authString = QByteArray::fromBase64(rx.cap(1).toAscii()).replace((char)0, ""); // authString is like : username="",nonce="",cnonce="",nc=,qop=auth,digest-uri="",response=,charset=utf-8 // Parse values rx.setPattern("username=\"([^\"]*)\",nonce=\"([^\"]*)\",cnonce=\"([^\"]*)\",nc=([^,]*),qop=auth,digest-uri=\"([^\"]*)\",response=([^,]*),charset=utf-8"); if(rx.indexIn(authString) != -1) { QByteArray const username = rx.cap(1).toAscii(); Bunny * bunny = BunnyManager::GetBunny(username); // Check if we want to bypass auth for this bunny if((GlobalSettings::Get("Config/StandAloneAuthBypass", false)) == true && (username == GlobalSettings::GetString("Config/StandAloneAuthBypassBunny"))) { // Send success LogInfo("Sending success instead of password verification"); answer.append("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); bunny->Authenticating(); *pBunny = bunny; // Auth OK, set current bunny xmpp->currentAuthStep = 4; return true; } QByteArray const password = bunny->GetBunnyPassword(); QByteArray const nonce = rx.cap(2).toAscii(); QByteArray const cnonce = rx.cap(3).toAscii().append((char)0); // cnonce have a dummy \0 at his end :( QByteArray const nc = rx.cap(4).toAscii(); QByteArray const digest_uri = rx.cap(5).toAscii(); QByteArray const bunnyResponse = rx.cap(6).toAscii(); if(bunnyResponse == ComputeResponse(username, password, nonce, cnonce, nc, digest_uri, "AUTHENTICATE")) { // Send challenge back // <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>...</challenge> // rspauth=... QByteArray const rspAuth = "rspauth=" + ComputeResponse(username, password, nonce, cnonce, nc, digest_uri, ""); answer.append("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + rspAuth.toBase64() + "</challenge>"); bunny->Authenticating(); *pBunny = bunny; // Auth OK, set current bunny xmpp->currentAuthStep = 3; return true; } LogError("Authentication failure for bunny"); // Bad password, send failure and restart auth answer.append("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>"); xmpp->currentAuthStep = 0; return true; } } LogError("Bad Auth Step 2, disconnect"); return false; } case 3: // We should receive <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/> if(data.startsWith("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>")) { // Send success answer.append("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); xmpp->currentAuthStep = 4; return true; } LogError("Bad Auth Step 3, disconnect"); return false; case 4: // We should receive <?xml version='1.0' encoding='UTF-8'?> if(data.startsWith("<?xml version='1.0' encoding='UTF-8'?>")) { // Send success answer.append("<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='1331400675' from='xmpp.nabaztag.com' version='1.0' xml:lang='en'>"); answer.append("<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind><unbind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></stream:features>"); xmpp->currentAuthStep = 0; (*pBunny)->Authenticated(); (*pBunny)->SetXmppHandler(xmpp); // Bunny is now authenticated return true; } LogError("Bad Auth Step 4, disconnect"); return false; case 100: // Register Bunny { // We should receive <iq to='xmpp.nabaztag.com' type='set' id='2'><query xmlns="violet:iq:register"><username>0019db01dbd7</username><password>208e6d83bfb2</password></query></iq> IQ iqAuth(data); if(iqAuth.IsValid() && iqAuth.Type() == IQ::Iq_Set) { QByteArray content = iqAuth.Content(); QRegExp rx("<query xmlns=\"violet:iq:register\"><username>([0-9a-f]*)</username><password>([0-9a-f]*)</password></query>"); if(rx.indexIn(content) != -1) { QByteArray user = rx.cap(1).toAscii(); QByteArray password = rx.cap(2).toAscii(); Bunny * bunny = BunnyManager::GetBunny(user); if(bunny->SetBunnyPassword(ComputeXor(user,password))) { answer.append(iqAuth.Reply(IQ::Iq_Result, "%1 %2 %3 %4", content)); xmpp->currentAuthStep = 1; return true; } LogError(QString("Password already set for bunny : ").append(QString(user))); return false; } } LogError("Bad Register, disconnect"); return false; } default: LogError("Unknown Auth Step, disconnect"); return false; } }