changeset 25:dd1489098265

basic http authentication
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 28 Aug 2012 11:20:49 +0200
parents 166664f0f860
children 6ba765ecf3db
files Core/HttpServer/MongooseServer.cpp Core/HttpServer/MongooseServer.h PalantirServer/PalantirInitialization.cpp PalantirServer/PalantirInitialization.h PalantirServer/main.cpp Resources/Configuration.json
diffstat 6 files changed, 99 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/MongooseServer.cpp	Tue Aug 28 10:42:43 2012 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Tue Aug 28 11:20:49 2012 +0200
@@ -36,6 +36,9 @@
 #include "mongoose.h"
 
 
+#define PALANTIR_REALM "Palantir Secure Area"
+
+
 namespace Palantir
 {
   static const char multipart[] = "multipart/form-data; boundary=";
@@ -394,19 +397,35 @@
   }
 
 
-  static bool Authorize(MongooseServer& that,
-                        HttpOutput& output,
-                        struct mg_connection *connection,
-                        const struct mg_request_info *request)
+  static bool Authorize(const MongooseServer& that,
+                        const HttpHandler::Arguments& headers,
+                        HttpOutput& output)
   {
-    /*std::string s = "HTTP/1.0 401 Unauthorized\r\n" 
-      "WWW-Authenticate: Digest realm=\"www.palanthir.com\",qop=\"auth\",nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\""
-      "\r\n\r\n";
-    output.Send(&s[0], s.size());
+    bool granted = false;
+
+    HttpHandler::Arguments::const_iterator auth = headers.find("authorization");
+    if (auth != headers.end())
+    {
+      std::string s = auth->second;
+      if (s.substr(0, 6) == "Basic ")
+      {
+        std::string b64 = s.substr(6);
+        granted = that.IsValidBasicHttpAuthentication(b64);
+      }
+    }
 
-    return false;*/
-
-    return true;
+    if (!granted)
+    {
+      std::string s = "HTTP/1.1 401 Unauthorized\r\n" 
+        "WWW-Authenticate: Basic realm=\"" PALANTIR_REALM "\""
+        "\r\n\r\n";
+      output.Send(&s[0], s.size());
+      return false;
+    }
+    else
+    {
+      return true;
+    }
   }
 
 
@@ -429,15 +448,9 @@
         headers.insert(std::make_pair(name, request->http_headers[i].value));
       }
 
-      printf("=========================\n");
-      printf(" URI: [%s]\n", request->uri);
-      for (HttpHandler::Arguments::const_iterator i = headers.begin(); i != headers.end(); i++)
-      {
-        printf("[%s] = [%s]\n", i->first.c_str(), i->second.c_str());
-      }
-
       // Authenticate this connection
-      if (!Authorize(*that, c, connection, request))
+      if (that->IsAuthenticationEnabled() &&
+          !Authorize(*that, headers, c))
       {
         return (void*) "";
       }
@@ -530,6 +543,7 @@
   MongooseServer::MongooseServer() : pimpl_(new PImpl)
   {
     pimpl_->context_ = NULL;
+    authentication_ = false;
     ssl_ = false;
     port_ = 8000;
   }
@@ -604,6 +618,13 @@
   }
 
 
+  void MongooseServer::ClearUsers()
+  {
+    Stop();
+    registeredUsers_.clear();
+  }
+
+
   void MongooseServer::RegisterUser(const char* username,
                                     const char* password)
   {
@@ -620,7 +641,7 @@
 #if PALANTIR_SSL_ENABLED == 0
     if (enabled)
     {
-      throw PalantirException("Palantir has been build without SSL support");
+      throw PalantirException("Palantir has been built without SSL support");
     }
     else
     {
@@ -631,9 +652,20 @@
 #endif
   }
 
+  void MongooseServer::SetAuthenticationEnabled(bool enabled)
+  {
+    Stop();
+    authentication_ = enabled;
+  }
+
   void MongooseServer::SetSslCertificate(const char* path)
   {
     Stop();
     certificate_ = path;
   }
+
+  bool MongooseServer::IsValidBasicHttpAuthentication(const std::string& basic) const
+  {
+    return registeredUsers_.find(basic) != registeredUsers_.end();
+  }
 }
--- a/Core/HttpServer/MongooseServer.h	Tue Aug 28 10:42:43 2012 +0200
+++ b/Core/HttpServer/MongooseServer.h	Tue Aug 28 11:20:49 2012 +0200
@@ -44,6 +44,7 @@
     typedef std::set<std::string> RegisteredUsers;
     RegisteredUsers registeredUsers_;
 
+    bool authentication_;
     bool ssl_;
     std::string certificate_;
     uint16_t port_;
@@ -66,11 +67,20 @@
 
     void Stop();
 
+    void ClearUsers();
+
     void RegisterUser(const char* username,
                       const char* password);
 
     void RegisterHandler(HttpHandler* handler);  // This takes the ownership
 
+    bool IsAuthenticationEnabled() const
+    {
+      return authentication_;
+    }
+
+    void SetAuthenticationEnabled(bool enabled);
+
     bool IsSslEnabled() const
     {
       return ssl_;
@@ -91,5 +101,7 @@
     HttpHandler* FindHandler(const UriComponents& forUri) const;
 
     ChunkStore& GetChunkStore();
+
+    bool IsValidBasicHttpAuthentication(const std::string& basic) const;
   };
 }
--- a/PalantirServer/PalantirInitialization.cpp	Tue Aug 28 10:42:43 2012 +0200
+++ b/PalantirServer/PalantirInitialization.cpp	Tue Aug 28 11:20:49 2012 +0200
@@ -205,4 +205,32 @@
       target.insert(members[i]);
     }
   }
+
+
+
+  void SetupRegisteredUsers(MongooseServer& httpServer)
+  {
+    boost::mutex::scoped_lock lock(globalMutex_);
+
+    httpServer.ClearUsers();
+
+    if (!configuration_->isMember("RegisteredUsers"))
+    {
+      return;
+    }
+
+    const Json::Value& users = (*configuration_) ["RegisteredUsers"];
+    if (users.type() != Json::objectValue)
+    {
+      throw PalantirException("Badly formatted list of users");
+    }
+
+    Json::Value::Members usernames = users.getMemberNames();
+    for (size_t i = 0; i < usernames.size(); i++)
+    {
+      const std::string& username = usernames[i];
+      std::string password = users[username].asString();
+      httpServer.RegisterUser(username.c_str(), password.c_str());
+    }
+  }
 }
--- a/PalantirServer/PalantirInitialization.h	Tue Aug 28 10:42:43 2012 +0200
+++ b/PalantirServer/PalantirInitialization.h	Tue Aug 28 11:20:49 2012 +0200
@@ -23,6 +23,7 @@
 #include <string>
 #include <set>
 #include <json/json.h>
+#include "../Core/HttpServer/MongooseServer.h"
 
 namespace Palantir
 {
@@ -45,4 +46,6 @@
                         int& port);
 
   void GetListOfDicomModalities(std::set<std::string>& target);
+
+  void SetupRegisteredUsers(MongooseServer& httpServer);
 }
--- a/PalantirServer/main.cpp	Tue Aug 28 10:42:43 2012 +0200
+++ b/PalantirServer/main.cpp	Tue Aug 28 11:20:49 2012 +0200
@@ -123,6 +123,9 @@
       MongooseServer httpServer;
       httpServer.SetPort(GetGlobalIntegerParameter("HttpPort", 8000));
 
+      httpServer.SetAuthenticationEnabled(GetGlobalBoolParameter("AuthenticationEnabled", false));
+      SetupRegisteredUsers(httpServer);
+
       if (GetGlobalBoolParameter("SslEnabled", false))
       {
         std::string certificate = GetGlobalStringParameter("SslCertificate", "certificate.pem");
--- a/Resources/Configuration.json	Tue Aug 28 10:42:43 2012 +0200
+++ b/Resources/Configuration.json	Tue Aug 28 11:20:49 2012 +0200
@@ -49,6 +49,7 @@
     },
 
 
+
     /**
      * Network topology
      **/