00001
00002
00003
00004
00005
00006
00007
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
00027 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00028 #endif
00029 #include <openssl/sha.h>
00030 #endif
00031
00032
00033 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
00084 SHA1((const unsigned char *)password.data(), password.size(), m_password_hash);
00085
00086
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
00102 if (password_hash.size() != SHA_DIGEST_LENGTH*2)
00103 BOOST_THROW_EXCEPTION( error::bad_password_hash() );
00104 m_password = password_hash;
00105
00106
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 }
00298
00299 #endif