pion-net
4.0.9
|
00001 // ------------------------------------------------------------------ 00002 // pion-net: a C++ framework for building lightweight HTTP interfaces 00003 // ------------------------------------------------------------------ 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.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_PIONUSER_HEADER__ 00011 #define __PION_PIONUSER_HEADER__ 00012 00013 #include <map> 00014 #include <string> 00015 #include <cstring> 00016 #include <boost/shared_ptr.hpp> 00017 #include <boost/noncopyable.hpp> 00018 #include <boost/thread/mutex.hpp> 00019 #include <boost/numeric/conversion/cast.hpp> 00020 #include <pion/PionConfig.hpp> 00021 #include <pion/PionException.hpp> 00022 00023 #ifdef PION_HAVE_SSL 00024 #include <openssl/sha.h> 00025 #endif 00026 00027 namespace pion { // begin namespace pion 00028 namespace net { // begin namespace net (Pion Network Library) 00029 00030 00034 class PionUser : 00035 private boost::noncopyable 00036 { 00037 public: 00038 00040 class BadPasswordHash : public std::exception { 00041 public: 00042 virtual const char* what() const throw() { 00043 return "Invalid password hash provided"; 00044 } 00045 }; 00046 00047 00049 PionUser(std::string const &username) : 00050 m_username(username) 00051 {} 00052 00054 PionUser(std::string const &username, std::string const &password) : 00055 m_username(username) 00056 { 00057 setPassword(password); 00058 } 00059 00061 virtual ~PionUser() {} 00062 00064 std::string const & getUsername() const { return m_username; } 00065 00067 std::string const & getPassword() const { return m_password; } 00068 00074 virtual bool matchPassword(const std::string& password) const { 00075 #ifdef PION_HAVE_SSL 00076 unsigned char sha1_hash[SHA_DIGEST_LENGTH]; 00077 SHA1(reinterpret_cast<const unsigned char *>(password.data()), password.size(), sha1_hash); 00078 return (memcmp(sha1_hash, m_password_hash, SHA_DIGEST_LENGTH) == 0); 00079 #else 00080 return m_password == password; 00081 #endif 00082 } 00083 00085 virtual void setPassword(const std::string& password) { 00086 #ifdef PION_HAVE_SSL 00087 // store encrypted hash value 00088 SHA1((const unsigned char *)password.data(), password.size(), m_password_hash); 00089 00090 // update password string (convert binary to hex) 00091 m_password.clear(); 00092 char buf[3]; 00093 for (unsigned int n = 0; n < SHA_DIGEST_LENGTH; ++n) { 00094 sprintf(buf, "%.2x", static_cast<unsigned int>(m_password_hash[n])); 00095 m_password += buf; 00096 } 00097 #else 00098 m_password = password; 00099 #endif 00100 } 00101 00102 #ifdef PION_HAVE_SSL 00103 00104 virtual void setPasswordHash(const std::string& password_hash) { 00105 // update password string representation 00106 if (password_hash.size() != SHA_DIGEST_LENGTH*2) 00107 throw BadPasswordHash(); 00108 m_password = password_hash; 00109 00110 // convert string from hex to binary value 00111 char buf[3]; 00112 buf[2] = '\0'; 00113 unsigned int hash_pos = 0; 00114 std::string::iterator str_it = m_password.begin(); 00115 while (str_it != m_password.end()) { 00116 buf[0] = *str_it; 00117 ++str_it; 00118 buf[1] = *str_it; 00119 ++str_it; 00120 m_password_hash[hash_pos++] = boost::numeric_cast<unsigned char>(strtoul(buf, 0, 16)); 00121 } 00122 } 00123 #endif 00124 00125 00126 protected: 00127 00129 const std::string m_username; 00130 00132 std::string m_password; 00133 00134 #ifdef PION_HAVE_SSL 00135 00136 unsigned char m_password_hash[SHA_DIGEST_LENGTH]; 00137 #endif 00138 }; 00139 00141 typedef boost::shared_ptr<PionUser> PionUserPtr; 00142 00143 00147 class PionUserManager : 00148 private boost::noncopyable 00149 { 00150 public: 00151 00153 PionUserManager(void) {} 00154 00156 virtual ~PionUserManager() {} 00157 00159 inline bool empty(void) const { 00160 boost::mutex::scoped_lock lock(m_mutex); 00161 return m_users.empty(); 00162 } 00163 00172 virtual bool addUser(const std::string &username, 00173 const std::string &password) 00174 { 00175 boost::mutex::scoped_lock lock(m_mutex); 00176 UserMap::iterator i = m_users.find(username); 00177 if (i!=m_users.end()) 00178 return false; 00179 PionUserPtr user(new PionUser(username, password)); 00180 m_users.insert(std::make_pair(username, user)); 00181 return true; 00182 } 00183 00192 virtual bool updateUser(const std::string &username, 00193 const std::string &password) 00194 { 00195 boost::mutex::scoped_lock lock(m_mutex); 00196 UserMap::iterator i = m_users.find(username); 00197 if (i==m_users.end()) 00198 return false; 00199 i->second->setPassword(password); 00200 return true; 00201 } 00202 00203 #ifdef PION_HAVE_SSL 00204 00212 virtual bool addUserHash(const std::string &username, 00213 const std::string &password_hash) 00214 { 00215 boost::mutex::scoped_lock lock(m_mutex); 00216 UserMap::iterator i = m_users.find(username); 00217 if (i!=m_users.end()) 00218 return false; 00219 PionUserPtr user(new PionUser(username)); 00220 user->setPasswordHash(password_hash); 00221 m_users.insert(std::make_pair(username, user)); 00222 return true; 00223 } 00224 00233 virtual bool updateUserHash(const std::string &username, 00234 const std::string &password_hash) 00235 { 00236 boost::mutex::scoped_lock lock(m_mutex); 00237 UserMap::iterator i = m_users.find(username); 00238 if (i==m_users.end()) 00239 return false; 00240 i->second->setPasswordHash(password_hash); 00241 return true; 00242 } 00243 #endif 00244 00250 virtual bool removeUser(const std::string &username) { 00251 boost::mutex::scoped_lock lock(m_mutex); 00252 UserMap::iterator i = m_users.find(username); 00253 if (i==m_users.end()) 00254 return false; 00255 m_users.erase(i); 00256 return true; 00257 } 00258 00262 virtual PionUserPtr getUser(const std::string &username) { 00263 boost::mutex::scoped_lock lock(m_mutex); 00264 UserMap::const_iterator i = m_users.find(username); 00265 if (i==m_users.end()) 00266 return PionUserPtr(); 00267 else 00268 return i->second; 00269 } 00270 00274 virtual PionUserPtr getUser(const std::string& username, const std::string& password) { 00275 boost::mutex::scoped_lock lock(m_mutex); 00276 UserMap::const_iterator i = m_users.find(username); 00277 if (i==m_users.end() || !i->second->matchPassword(password)) 00278 return PionUserPtr(); 00279 else 00280 return i->second; 00281 } 00282 00283 00284 protected: 00285 00287 typedef std::map<std::string, PionUserPtr> UserMap; 00288 00289 00291 mutable boost::mutex m_mutex; 00292 00294 UserMap m_users; 00295 }; 00296 00298 typedef boost::shared_ptr<PionUserManager> PionUserManagerPtr; 00299 00300 00301 } // end namespace net 00302 } // end namespace pion 00303 00304 #endif