bool BZFSHTTPAuth::generatePage ( const HTTPRequest &request, HTTPReply &reply ) { if (!authPage.size()) setupAuth(); flushTasks(); int sessionID = request.sessionID; reply.docType = HTTPReply::eHTML; reply.returnCode = HTTPReply::e200OK; std::map<int,AuthInfo>::iterator authItr = authedSessions.find(sessionID); if ( authItr != authedSessions.end() ) // it is one of our authorized users, be nice and forward the request to our child { // put this back to the default reply.docType = HTTPReply::eText; authItr->second.time = bz_getCurrentTime(); bool complete = handleAuthedRequest(authItr->second.level,request,reply); if (!complete) defferedAuthedRequests.push_back(request.requestID); return complete; } else // they are not fully authorized yet { std::map<int,PendingTokenTask*>::iterator pendingItr = pendingTokenTasks.find(request.requestID); if (pendingItr != pendingTokenTasks.end()) // they have a token, check it { AuthInfo info; info.time = bz_getCurrentTime(); if (!pendingItr->second->groups.size()) info.level = -1; else { if (pendingItr->second->groups.size() == 1) { info.username = pendingItr->second->groups[0]; info.level = 0; // just authed, no levels } else { info.username = pendingItr->second->groups[0]; info.level = getLevelFromGroups(pendingItr->second->groups); info.groups = pendingItr->second->groups; info.groups.erase(info.groups.begin()); // pull off the first 'group' because it's a name } if (info.level >= 0) authedSessions[request.sessionID] = info; } delete(pendingItr->second); pendingTokenTasks.erase(pendingItr); // put this back to the default reply.docType = HTTPReply::eText; bool complete = handleAuthedRequest(info.level,request,reply); if (!complete) defferedAuthedRequests.push_back(request.requestID); return complete; } else { std::string action,user,token; request.getParam("action",action); request.getParam("user",user); request.getParam("token",token); if (compare_nocase(action,"login") == 0 && user.size() && token.size()) // it's a response from weblogin return verifyToken(request,reply); else { // it's someone we know NOTHING about, send them the login templateSystem.startTimer(); size_t s = authPage.find_last_of('.'); if (s != std::string::npos) { if (compare_nocase(authPage.c_str()+s,".tmpl") == 0) { if(!templateSystem.processTemplateFile(reply.body,authPage.c_str())) templateSystem.processTemplate(reply.body,authPage); } else templateSystem.processTemplate(reply.body,authPage); } else templateSystem.processTemplate(reply.body,authPage); } } } return true; }
bool BZFSHTTPAuth::verifyToken ( const HTTPRequest &request, HTTPReply &reply ) { // build up the groups list std::string token,user; request.getParam("token",token); request.getParam("user",user); std::vector<std::string> groups; std::map<int, std::vector<std::string> >::iterator itr = authLevels.begin(); while (itr != authLevels.end()) { for (size_t i = 0; i < itr->second.size();i++) { std::string &perm = itr->second[i]; std::vector<std::string> groupsWithPerm; if (compare_nocase(perm,"ADMIN")==0) groupsWithPerm = findGroupsWithAdmin(); else groupsWithPerm = findGroupsWithPerm(perm); // only add groups that are not in the list yet for (size_t g = 0; g < groupsWithPerm.size(); g++) { if (std::find(groups.begin(),groups.end(),groupsWithPerm[g]) == groups.end()) groups.push_back(groupsWithPerm[g]); } } itr++; } PendingTokenTask *task = new PendingTokenTask; if (!user.size() || !token.size()) { reply.body += "Invalid response"; reply.docType = HTTPReply::eText; return true; } task->requestID = request.requestID; task->URL = "http://my.bzflag.org/db/"; task->URL += "?action=CHECKTOKENS&checktokens=" + url_encode(user); if (!ipIsLocal(request.ip)) task->URL += "@" + request.ip; task->URL += "%3D" + token; task->URL += "&groups="; for (size_t g = 0; g < groups.size(); g++) { task->URL += groups[g]; if ( g+1 < groups.size()) task->URL += "%0D%0A"; } // give the task to bzfs and let it do it, when it's done it'll be processed bz_addURLJob(task->URL.c_str(),task); return false; }