- Main Page
- Classes
- Files

- File List

# include/pion/user.hpp

    00001 // ---------------------------------------------------------------------
    00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
    00003 // ---------------------------------------------------------------------
    00004 // Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_USER_HEADER__
    00011 #define __PION_USER_HEADER__
    00012
    00013 #include <map>
    00014 #include <string>
    00015 #include <cstdio>
    00016 #include <cstring>
    00017 #include <boost/shared_ptr.hpp>
    00018 #include <boost/noncopyable.hpp>
    00019 #include <boost/thread/mutex.hpp>
    00020 #include <boost/numeric/conversion/cast.hpp>
    00021 #include <pion/config.hpp>
    00022 #include <pion/error.hpp>
    00023
    00024 #ifdef PION_HAVE_SSL
    00025     #if defined(__APPLE__)
    00026         // suppress warnings about OpenSSL being deprecated in OSX
    00027         #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    00028     #endif
    00029     #include <openssl/sha.h>
    00030 #endif
    00031
    00032
    00033 namespace pion {    // begin namespace pion
    00034
    00035
    00039 class user :
    00040     private boost::noncopyable
    00041 {
    00042 public:
    00043
    00045     user(std::string const &username) :
    00046         m_username(username)
    00047     {}
    00048
    00050     user(std::string const &username, std::string const &password) :
    00051         m_username(username)
    00052     {
    00053         set_password(password);
    00054     }
    00055
    00057     virtual ~user() {}
    00058
    00060     std::string const & get_username() const { return m_username; }
    00061
    00063     std::string const & get_password() const { return m_password; }
    00064
    00070     virtual bool match_password(const std::string& password) const {
    00071 #ifdef PION_HAVE_SSL
    00072         unsigned char sha1_hash[SHA_DIGEST_LENGTH];
    00073         SHA1(reinterpret_cast<const unsigned char *>(password.data()), password.size(), sha1_hash);
    00074         return (memcmp(sha1_hash, m_password_hash, SHA_DIGEST_LENGTH) == 0);
    00075 #else
    00076         return m_password == password;
    00077 #endif
    00078     }
    00079
    00081     virtual void set_password(const std::string& password) {
    00082 #ifdef PION_HAVE_SSL
    00083         // store encrypted hash value
    00084         SHA1((const unsigned char *)password.data(), password.size(), m_password_hash);
    00085
    00086         // update password string (convert binary to hex)
    00087         m_password.clear();
    00088         char buf[3];
    00089         for (unsigned int n = 0; n < SHA_DIGEST_LENGTH; ++n) {
    00090             sprintf(buf, "%.2x", static_cast<unsigned int>(m_password_hash[n]));
    00091             m_password += buf;
    00092         }
    00093 #else
    00094         m_password = password;
    00095 #endif
    00096     }
    00097
    00098 #ifdef PION_HAVE_SSL
    00100     virtual void set_password_hash(const std::string& password_hash) {
    00101         // update password string representation
    00102         if (password_hash.size() != SHA_DIGEST_LENGTH*2)
    00103             BOOST_THROW_EXCEPTION( error::bad_password_hash() );
    00104         m_password = password_hash;
    00105
    00106         // convert string from hex to binary value
    00107         char buf[3];
    00108         buf[2] = '\0';
    00109         unsigned int hash_pos = 0;
    00110         std::string::iterator str_it = m_password.begin();
    00111         while (str_it != m_password.end()) {
    00112             buf[0] = *str_it;
    00113             ++str_it;
    00114             buf[1] = *str_it;
    00115             ++str_it;
    00116             m_password_hash[hash_pos++] = boost::numeric_cast<unsigned char>(strtoul(buf, 0, 16));
    00117         }
    00118     }
    00119 #endif
    00120
    00121
    00122 protected:
    00123
    00125     const std::string   m_username;
    00126
    00128     std::string         m_password;
    00129
    00130 #ifdef PION_HAVE_SSL
    00132     unsigned char       m_password_hash[SHA_DIGEST_LENGTH];
    00133 #endif
    00134 };
    00135
    00137 typedef boost::shared_ptr<user> user_ptr;
    00138
    00139
    00143 class user_manager :
    00144     private boost::noncopyable
    00145 {
    00146 public:
    00147
    00149     user_manager(void) {}
    00150
    00152     virtual ~user_manager() {}
    00153
    00155     inline bool empty(void) const {
    00156         boost::mutex::scoped_lock lock(m_mutex);
    00157         return m_users.empty();
    00158     }
    00159
    00168     virtual bool add_user(const std::string &username,
    00169         const std::string &password)
    00170     {
    00171         boost::mutex::scoped_lock lock(m_mutex);
    00172         user_map_t::iterator i = m_users.find(username);
    00173         if (i!=m_users.end())
    00174             return false;
    00175         user_ptr user_ptr(new user(username, password));
    00176         m_users.insert(std::make_pair(username, user_ptr));
    00177         return true;
    00178     }
    00179
    00188     virtual bool update_user(const std::string &username,
    00189         const std::string &password)
    00190     {
    00191         boost::mutex::scoped_lock lock(m_mutex);
    00192         user_map_t::iterator i = m_users.find(username);
    00193         if (i==m_users.end())
    00194             return false;
    00195         i->second->set_password(password);
    00196         return true;
    00197     }
    00198
    00199 #ifdef PION_HAVE_SSL
    00200
    00208     virtual bool add_user_hash(const std::string &username,
    00209         const std::string &password_hash)
    00210     {
    00211         boost::mutex::scoped_lock lock(m_mutex);
    00212         user_map_t::iterator i = m_users.find(username);
    00213         if (i!=m_users.end())
    00214             return false;
    00215         user_ptr user_ptr(new user(username));
    00216         user_ptr->set_password_hash(password_hash);
    00217         m_users.insert(std::make_pair(username, user_ptr));
    00218         return true;
    00219     }
    00220
    00229     virtual bool update_user_hash(const std::string &username,
    00230         const std::string &password_hash)
    00231     {
    00232         boost::mutex::scoped_lock lock(m_mutex);
    00233         user_map_t::iterator i = m_users.find(username);
    00234         if (i==m_users.end())
    00235             return false;
    00236         i->second->set_password_hash(password_hash);
    00237         return true;
    00238     }
    00239 #endif
    00240
    00246     virtual bool remove_user(const std::string &username) {
    00247         boost::mutex::scoped_lock lock(m_mutex);
    00248         user_map_t::iterator i = m_users.find(username);
    00249         if (i==m_users.end())
    00250             return false;
    00251         m_users.erase(i);
    00252         return true;
    00253     }
    00254
    00258     virtual user_ptr get_user(const std::string &username) {
    00259         boost::mutex::scoped_lock lock(m_mutex);
    00260         user_map_t::const_iterator i = m_users.find(username);
    00261         if (i==m_users.end())
    00262             return user_ptr();
    00263         else
    00264             return i->second;
    00265     }
    00266
    00270     virtual user_ptr get_user(const std::string& username, const std::string& password) {
    00271         boost::mutex::scoped_lock lock(m_mutex);
    00272         user_map_t::const_iterator i = m_users.find(username);
    00273         if (i==m_users.end() || !i->second->match_password(password))
    00274             return user_ptr();
    00275         else
    00276             return i->second;
    00277     }
    00278
    00279
    00280 protected:
    00281
    00283     typedef std::map<std::string, user_ptr>  user_map_t;
    00284
    00285
    00287     mutable boost::mutex    m_mutex;
    00288
    00290     user_map_t              m_users;
    00291 };
    00292
    00294 typedef boost::shared_ptr<user_manager>  user_manager_ptr;
    00295
    00296
    00297 }   // end namespace pion
    00298
    00299 #endif