QSharedPointer<User> QueryExecutor::insertNewUser(const QSharedPointer<User>& user) { bool result; QSqlQuery newUserQuery(m_database); qlonglong newId = nextUserKey(); syslog(LOG_INFO,"Generating token for new user, %s : %s",user->getLogin().toStdString().c_str() ,user->getPassword().toStdString().c_str()); QString newToken = generateNewToken(user->getLogin(),user->getPassword()); // syslog(LOG_INFO,"newToken = %s",newToken.toStdString().c_str()); newUserQuery.prepare("insert into users (id,login,password,token) values(:id,:login,:password,:a_t);"); newUserQuery.bindValue(":id",newId); syslog(LOG_INFO,"Sending: %s",newUserQuery.lastQuery().toStdString().c_str()); newUserQuery.bindValue(":login",user->getLogin()); syslog(LOG_INFO,"Sending: %s",newUserQuery.lastQuery().toStdString().c_str()); newUserQuery.bindValue(":password",user->getPassword()); syslog(LOG_INFO,"Sending: %s",newUserQuery.lastQuery().toStdString().c_str()); newUserQuery.bindValue(":a_t",newToken); syslog(LOG_INFO,"Sending: %s",newUserQuery.lastQuery().toStdString().c_str()); m_database.transaction(); result=newUserQuery.exec(); if(!result) { syslog(LOG_INFO,"Rollback for NewUser sql query"); m_database.rollback(); return QSharedPointer<User>(NULL); }else { syslog(LOG_INFO,"Commit for NewUser sql query"); m_database.commit(); } QSharedPointer<DbUser> newUser(new DbUser(user->getLogin(),user->getPassword(),newId,newToken)); return newUser; }
//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); } }
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 }
QString AuthorizationManager::LoginService(bool localhost, QString service){ //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 // -- TO-DO //Now generate a new token and send it back return generateNewToken(); }
// ========================= // PRIVATE // ========================= QString AuthorizationManager::generateNewToken(){ QString tok; for(int i=0; i<TOKENLENGTH; i++){ tok.append( AUTHCHARS.at( qrand() % AUTHCHARS.length() ) ); } if(HASH.contains(tok)){ //Just in case the randomizer came up with something identical - re-run it tok = generateNewToken(); }else{ //unique token created - add it to the hash with the current time (+timeout) HASH.insert(tok, QDateTime::currentDateTime().addSecs(TIMEOUTSECS) ); } return tok; }
// == Token Generation functions QString AuthorizationManager::LoginUP(bool localhost, QString user, QString pass){ //Login w/ username & password bool ok = false; //First check that the user is valid on the system and part of the operator group if(user!="root"){ if(!getUserGroups(user).contains("operator")){ return ""; } //invalid user - needs to be part of operator group } //qDebug() << "Check username/password" << user << pass; //Need to run the full username/password through PAM ok = pam_checkPW(user,pass); qDebug() << "User Login Attempt:" << user << " Success:" << ok << " Local Login:"******""; } //invalid login else{ return generateNewToken(); } //valid login - generate a new token for it }
// ========================= // PRIVATE // ========================= QString AuthorizationManager::generateNewToken(bool isOp, QString user){ QString tok; for(int i=0; i<TOKENLENGTH; i++){ tok.append( AUTHCHARS.at( qrand() % AUTHCHARS.length() ) ); } if( !hashID(tok).isEmpty() ){ //Just in case the randomizer came up with something identical - re-run it tok = generateNewToken(isOp, user); }else{ //unique token created - add it to the hash with the current time (+timeout) QString id = tok + "::::"+(isOp ? "operator" : "user")+"::::"+user; //append operator status to auth key HASH.insert(id, QDateTime::currentDateTime().addSecs(TIMEOUTSECS) ); //qDebug() << "Current HASH Contents:" << HASH.keys(); } return tok; }
// == 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); } }