//======================= // PUBLIC //======================= WebServer::WebServer(){ //Setup all the various settings WSServer = 0; TCPServer = 0; AUTH = new AuthorizationManager(); connect(AUTH, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) ); }
QString AuthorizationManager::LoginService(QHostAddress host, QString service){ bool localhost = ( (host== QHostAddress::LocalHost) || (host== QHostAddress::LocalHostIPv6) || (host.toString()=="::ffff:127.0.0.1") ); //Login a particular automated service qDebug() << "Service Login Attempt:" << service << " Success:" << localhost; if(!localhost){ return ""; } //invalid - services must be local for access //Check that the service is valid on the system bool isok = localhost && CONFIG->value("auth/allowServiceAuth",false).toBool( ); if(service!="root" && service!="toor" && isok){ QStringList groups = getUserGroups(service); isok = (groups.contains(service) && !groups.contains("wheel") && !groups.contains("operator")); } //Now generate a new token and send it back if(!isok){ //invalid login if(!localhost){ //Bump the fail count for this host bool overlimit = BumpFailCount(host.toString()); if(overlimit){ emit BlockHost(host); } return (overlimit ? "REFUSED" : ""); }else{ return ""; } }else{ return generateNewToken(false, service); }//services are never given operator privileges }
//Stage 2 SSL Login Check: Verify that the returned/encrypted string can be decoded and matches the initial random string QString AuthorizationManager::LoginUC(QHostAddress host, QString encstring){ //Login w/ SSL certificate bool ok = false; //qDebug() << "SSL Auth Attempt"; //First clean out any old strings/keys QStringList pubkeys = QStringList(HASH.keys()).filter("SSL_CHECK_STRING/"); //temporary, re-use variable below for(int i=0; i<pubkeys.length(); i++){ //Check expiration time on each initial string if(QDateTime::currentDateTime() > HASH[pubkeys[i]]){ //Note: normally only 1 request per user at a time, but it is possible for a couple different clients to try // and authenticate as the same user (but different keys) at nearly the same time - so keep a short valid-string time frame (<30 seconds) // to mitigate this possibility (need to prevent the second user-auth request from invalidating the first before the first auth handshake is finished) HASH.remove(pubkeys[i]); //initstring expired - go ahead and remove it to reduce calc time later } } //Now re-use the "pubkeys" variable for the public SSL keys QString user; pubkeys = CONFIG->allKeys().filter("RegisteredCerts/"); //Format: "RegisteredCerts/<user>/<key>" //qDebug() << " - Check pubkeys";// << pubkeys; for(int i=0; i<pubkeys.length() && !ok; i++){ //Decrypt the string with this pubkey - and compare to the outstanding initstrings QString key = DecryptSSLString(encstring, pubkeys[i].section("/",2,-1)); if(HASH.contains("SSL_CHECK_STRING/"+key)){ //Valid reponse found //qDebug() << " - Found Valid Key"; ok = true; //Remove the initstring from the hash (already used) HASH.remove("SSL_CHECK_STRING/"+key); user = pubkeys[i].section("/",1,1); } } bool isOperator = false; if(ok){ //qDebug() << "Check user groups"; //First check that the user is valid on the system and part of the operator group if(user!="root" && user!="toor"){ QStringList groups = getUserGroups(user); if(groups.contains("wheel")){ isOperator = true; } //full-access user else if(!groups.contains("operator")){ return ""; //user not allowed access if not in either of the wheel/operator groups } }else{ isOperator = true; } } if(user.isEmpty()){ ok = false; } qDebug() << "User Login Attempt:" << user << " Success:" << ok << " IP:" << host.toString(); LogManager::log(LogManager::HOST, QString("User Login Attempt: ")+user+" Success: "+(ok?"true":"false")+" IP: "+host.toString() ); if(!ok){ //invalid login //Bump the fail count for this host bool overlimit = BumpFailCount(host.toString()); if(overlimit){ emit BlockHost(host); } return (overlimit ? "REFUSED" : ""); }else{ //valid login - generate a new token for it ClearHostFail(host.toString()); return generateNewToken(isOperator, user); } }
//======================= // PUBLIC //======================= WebServer::WebServer(){ //Setup all the various settings WSServer = 0; TCPServer = 0; bridgeTimer = new QTimer(this); bridgeTimer->setInterval(60000); //1 minute connect(bridgeTimer, SIGNAL(timeout()), this, SLOT(checkBridges()) ); AUTH = new AuthorizationManager(); connect(AUTH, SIGNAL(BlockHost(QHostAddress)), this, SLOT(BlackListConnection(QHostAddress)) ); }
// == Token Generation functions QString AuthorizationManager::LoginUP(QHostAddress host, QString user, QString pass){ //Login w/ username & password bool localhost = ( (host== QHostAddress::LocalHost) || (host== QHostAddress::LocalHostIPv6) || (host.toString()=="::ffff:127.0.0.1") ); bool ok = false; bool isOperator = false; //First check that the user is valid on the system and part of the operator group if( CONFIG->value("auth/allowUserPassAuth",true).toBool() ){ if(user!="root" && user!="toor"){ QStringList groups = getUserGroups(user); if(groups.contains("wheel")){ isOperator = true; } //full-access user else if(!groups.contains("operator")){ return ""; //user not allowed access if not in either of the wheel/operator groups } }else{ isOperator = true; } //qDebug() << "Check username/password" << user << pass << localhost; //Need to run the full username/password through PAM if(!localhost || user=="root" || user=="toor"){ ok = pam_checkPW(user,pass); }else{ ok = local_checkActive(user); //allow local access for users without password } } qDebug() << "User Login Attempt:" << user << " Success:" << ok << " IP:" << host.toString(); LogManager::log(LogManager::HOST, QString("User Login Attempt: ")+user+" Success: "+(ok?"true":"false")+" IP: "+host.toString() ); if(!ok){ //invalid login //Bump the fail count for this host bool overlimit = BumpFailCount(host.toString()); if(overlimit){ emit BlockHost(host); } return (overlimit ? "REFUSED" : ""); }else{ //valid login - generate a new token for it ClearHostFail(host.toString()); return generateNewToken(isOperator, user); } }