Added new API JSON-based auth scheme
This commit is contained in:
		
							parent
							
								
									74baf8d4a4
								
							
						
					
					
						commit
						f126b17ed1
					
				
					 1 changed files with 40 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -12,6 +12,15 @@
 | 
			
		|||
#include "controller_capabilities.h"
 | 
			
		||||
#include "controller_statistics.h"
 | 
			
		||||
 | 
			
		||||
/// Returns the challenge string for authentication, given the socket connection.
 | 
			
		||||
std::string getChallenge(Socket::Connection & conn){
 | 
			
		||||
  time_t Time = time(0);
 | 
			
		||||
  tm * TimeInfo = localtime( &Time);
 | 
			
		||||
  std::stringstream Date;
 | 
			
		||||
  Date << TimeInfo->tm_mday << "-" << TimeInfo->tm_mon << "-" << TimeInfo->tm_year + 1900;
 | 
			
		||||
  return Secure::md5(Date.str().c_str() + conn.getHost());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///\brief Checks an authorization request for a given user.
 | 
			
		||||
///\param Request The request to be parsed.
 | 
			
		||||
///\param Response The location to store the generated response.
 | 
			
		||||
| 
						 | 
				
			
			@ -57,12 +66,8 @@
 | 
			
		|||
/// Please note that this is NOT secure. At all. Never use this mechanism over a public network!
 | 
			
		||||
/// A status of `"ACC_MADE"` indicates the account was created successfully and can now be used to login as normal.
 | 
			
		||||
bool Controller::authorize(JSON::Value & Request, JSON::Value & Response, Socket::Connection & conn){
 | 
			
		||||
  time_t Time = time(0);
 | 
			
		||||
  tm * TimeInfo = localtime( &Time);
 | 
			
		||||
  std::stringstream Date;
 | 
			
		||||
  std::string Challenge = getChallenge(conn);
 | 
			
		||||
  std::string retval;
 | 
			
		||||
  Date << TimeInfo->tm_mday << "-" << TimeInfo->tm_mon << "-" << TimeInfo->tm_year + 1900;
 | 
			
		||||
  std::string Challenge = Secure::md5(Date.str().c_str() + conn.getHost());
 | 
			
		||||
  if (Request.isMember("authorize") && Request["authorize"]["username"].asString() != ""){
 | 
			
		||||
    std::string UserID = Request["authorize"]["username"];
 | 
			
		||||
    if (Storage["account"].isMember(UserID)){
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +107,36 @@ int Controller::handleAPIConnection(Socket::Connection & conn){
 | 
			
		|||
  //while connected and not past login attempt limit
 | 
			
		||||
  while (conn && logins < 4){
 | 
			
		||||
    if ((conn.spool() || conn.Received().size()) && H.Read(conn)){
 | 
			
		||||
      //Are we local and not forwarded? Instant-authorized.
 | 
			
		||||
      if (!authorized && !H.hasHeader("X-Real-IP") && conn.isLocal()){
 | 
			
		||||
        MEDIUM_MSG("Local API access automatically authorized");
 | 
			
		||||
        authorized = true;
 | 
			
		||||
      }
 | 
			
		||||
      #ifdef NOAUTH
 | 
			
		||||
      //If auth is disabled, always allow access.
 | 
			
		||||
      authorized = true;
 | 
			
		||||
      #endif
 | 
			
		||||
      if (!authorized && H.hasHeader("Authorization")){
 | 
			
		||||
        std::string auth = H.GetHeader("Authorization");
 | 
			
		||||
        if (auth.substr(0, 5) == "json "){
 | 
			
		||||
          INFO_MSG("Checking auth header");
 | 
			
		||||
          JSON::Value req;
 | 
			
		||||
          req["authorize"] = JSON::fromString(auth.substr(5));
 | 
			
		||||
          if (Storage["account"]){
 | 
			
		||||
            tthread::lock_guard<tthread::mutex> guard(configMutex);
 | 
			
		||||
            authorized = authorize(req, req, conn);
 | 
			
		||||
            if (!authorized){
 | 
			
		||||
              H.Clean();
 | 
			
		||||
              H.body = "Please login first or provide a valid token authentication.";
 | 
			
		||||
              H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
 | 
			
		||||
              H.SetHeader("WWW-Authenticate", "json "+req["authorize"].toString());
 | 
			
		||||
              H.SendResponse("403", "Not authorized", conn);
 | 
			
		||||
              H.Clean();
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      JSON::Value Response;
 | 
			
		||||
      JSON::Value Request = JSON::fromString(H.GetVar("command"));
 | 
			
		||||
      //invalid request? send the web interface, unless requested as "/api"
 | 
			
		||||
| 
						 | 
				
			
			@ -123,11 +158,6 @@ int Controller::handleAPIConnection(Socket::Connection & conn){
 | 
			
		|||
      }
 | 
			
		||||
      {//lock the config mutex here - do not unlock until done processing
 | 
			
		||||
        tthread::lock_guard<tthread::mutex> guard(configMutex);
 | 
			
		||||
        //Are we local and not forwarded? Instant-authorized.
 | 
			
		||||
        if (!authorized && !H.hasHeader("X-Real-IP") && conn.isLocal()){
 | 
			
		||||
          MEDIUM_MSG("Local API access automatically authorized");
 | 
			
		||||
          authorized = true;
 | 
			
		||||
        }
 | 
			
		||||
        //if already authorized, do not re-check for authorization
 | 
			
		||||
        if (authorized && Storage["account"]){
 | 
			
		||||
          Response["authorize"]["status"] = "OK";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue