From d93b0a5ba7eafd5eb59a4bee09af28624abe0e2a Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 13 Jan 2016 13:12:10 -0500 Subject: [PATCH] Add a new auth subsystem to teh backend of the server. Now the user's who login are divided up into "Full Access" users or not. This allows for additional restrictions in the backend subsystems to restrict certain types of operations to only the "full access" (root-permissioned) users. The users are divided up like this: 1) The user must be in either the "wheel" or "operator" groups to get any access whatsoever (restricting automated services from connecting). 2) If the user is in the "wheel" group, they get full access to the server's capabilities 3) If the user is in the "operator" group instead, then they only get limited access to the server's capabilities. While here, also allow password-less logins to the server if the client is connecting to a server on the same system (local access). User restrictions still apply. --- src/server/AuthorizationManager.cpp | 56 +++++++++++++++++++++-------- src/server/AuthorizationManager.h | 12 ++++++- src/server/WebSocket.cpp | 2 +- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/server/AuthorizationManager.cpp b/src/server/AuthorizationManager.cpp index 5d1a0db..d1abcf3 100644 --- a/src/server/AuthorizationManager.cpp +++ b/src/server/AuthorizationManager.cpp @@ -35,16 +35,30 @@ AuthorizationManager::~AuthorizationManager(){ // == Token Interaction functions == void AuthorizationManager::clearAuth(QString token){ //clear an authorization token - if(HASH.contains(token)){ HASH.remove(token); } + QString id = hashID(token); + if(!id.isEmpty()){ HASH.remove(id); } } bool AuthorizationManager::checkAuth(QString token){ //see if the given token is valid bool ok = false; - if(HASH.contains(token)){ + QString id = hashID(token); + if(!id.isEmpty()){ //Also verify that the token has not timed out - ok = (HASH[token] > QDateTime::currentDateTime()); - if(ok){ HASH.insert(token, QDateTime::currentDateTime().addSecs(TIMEOUTSECS)); } //valid - bump the timestamp + ok = (HASH[id] > QDateTime::currentDateTime()); + if(ok){ HASH.insert(id, QDateTime::currentDateTime().addSecs(TIMEOUTSECS)); } //valid - bump the timestamp + } + return ok; +} + +bool AuthorizationManager::hasFullAccess(QString token){ + bool ok = false; + QString id = hashID(token); + if(!id.isEmpty()){ + //Also verify that the token has not timed out + if( HASH[id] > QDateTime::currentDateTime() ){ + ok = id.section("::::",1,1)=="operator"; + } } return ok; } @@ -61,16 +75,25 @@ 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 - } + bool isOperator = false; + 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; //Need to run the full username/password through PAM - ok = pam_checkPW(user,pass); + if(!localhost || user=="root" || user=="toor"){ + ok = pam_checkPW(user,pass); + }else{ + ok = true; //allow local access for users without password + } qDebug() << "User Login Attempt:" << user << " Success:" << ok << " Local Login:" << localhost; if(!ok){ return ""; } //invalid login - else{ return generateNewToken(); } //valid login - generate a new token for it + else{ return generateNewToken(isOperator); } //valid login - generate a new token for it } QString AuthorizationManager::LoginService(bool localhost, QString service){ @@ -81,23 +104,25 @@ QString AuthorizationManager::LoginService(bool localhost, QString service){ // -- TO-DO //Now generate a new token and send it back - return generateNewToken(); + return generateNewToken(false); //services are never given operator privileges } // ========================= // PRIVATE // ========================= -QString AuthorizationManager::generateNewToken(){ +QString AuthorizationManager::generateNewToken(bool isOp){ QString tok; for(int i=0; i #include +#include #include class AuthorizationManager{ @@ -18,6 +19,8 @@ public: // == Token Interaction functions == void clearAuth(QString token); //clear an authorization token bool checkAuth(QString token); //see if the given token is valid + bool hasFullAccess(QString token); //see if the token is associated with a full-access account + int checkAuthTimeoutSecs(QString token); //Return the number of seconds that a token is valid for // == Token Generation functions @@ -26,9 +29,16 @@ public: private: QHash HASH; - QString generateNewToken(); + QString generateNewToken(bool isOperator); QStringList getUserGroups(QString user); + //token->hashID filter simplification + QString hashID(QString token){ + QStringList tmp = QStringList(HASH.keys()).filter(token+"::::"); + if(tmp.isEmpty()){ return ""; } + else{ return tmp.first(); } + } + //PAM login/check files bool pam_checkPW(QString user, QString pass); void pam_logFailure(int ret); diff --git a/src/server/WebSocket.cpp b/src/server/WebSocket.cpp index 6199a4b..325d0f1 100644 --- a/src/server/WebSocket.cpp +++ b/src/server/WebSocket.cpp @@ -7,7 +7,7 @@ #include -#define DEBUG 1 +#define DEBUG 0 #define IDLETIMEOUTMINS 30 WebSocket::WebSocket(QWebSocket *sock, QString ID, AuthorizationManager *auth){