pion  5.0.6
user.hpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #ifndef __PION_USER_HEADER__
11 #define __PION_USER_HEADER__
12 
13 #include <map>
14 #include <string>
15 #include <cstdio>
16 #include <cstring>
17 #include <boost/shared_ptr.hpp>
18 #include <boost/noncopyable.hpp>
19 #include <boost/thread/mutex.hpp>
20 #include <boost/numeric/conversion/cast.hpp>
21 #include <pion/config.hpp>
22 #include <pion/error.hpp>
23 
24 #ifdef PION_HAVE_SSL
25  #if defined(__APPLE__)
26  // suppress warnings about OpenSSL being deprecated in OSX
27  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
28  #endif
29  #include <openssl/sha.h>
30 #endif
31 
32 
33 namespace pion { // begin namespace pion
34 
35 
39 class user :
40  private boost::noncopyable
41 {
42 public:
43 
45  user(std::string const &username) :
46  m_username(username)
47 #ifdef PION_HAVE_SSL
48  , m_password_hash_type(EMPTY)
49 #endif
50  {}
51 
53  user(std::string const &username, std::string const &password) :
54  m_username(username)
55 #ifdef PION_HAVE_SSL
56  , m_password_hash_type(EMPTY)
57 #endif
58  {
59  set_password(password);
60  }
61 
63  virtual ~user() {}
64 
66  std::string const & get_username() const { return m_username; }
67 
69  std::string const & get_password() const { return m_password; }
70 
76  virtual bool match_password(const std::string& password) const {
77 #ifdef PION_HAVE_SSL
78  if (m_password_hash_type == SHA_256) {
79  unsigned char sha256_hash[SHA256_DIGEST_LENGTH];
80  SHA256(reinterpret_cast<const unsigned char *>(password.data()), password.size(), sha256_hash);
81  return (memcmp(sha256_hash, m_password_hash, SHA256_DIGEST_LENGTH) == 0);
82  } else if (m_password_hash_type == SHA_1) {
83  unsigned char sha1_hash[SHA_DIGEST_LENGTH];
84  SHA1(reinterpret_cast<const unsigned char *>(password.data()), password.size(), sha1_hash);
85  return (memcmp(sha1_hash, m_password_hash, SHA_DIGEST_LENGTH) == 0);
86  } else
87  return false;
88 #else
89  return m_password == password;
90 #endif
91  }
92 
94  virtual void set_password(const std::string& password) {
95 #ifdef PION_HAVE_SSL
96  // store encrypted hash value
97  SHA256((const unsigned char *)password.data(), password.size(), m_password_hash);
98  m_password_hash_type = SHA_256;
99 
100  // update password string (convert binary to hex)
101  m_password.clear();
102  char buf[3];
103  for (unsigned int n = 0; n < SHA256_DIGEST_LENGTH; ++n) {
104  sprintf(buf, "%.2x", static_cast<unsigned int>(m_password_hash[n]));
105  m_password += buf;
106  }
107 #else
108  m_password = password;
109 #endif
110  }
111 
112 #ifdef PION_HAVE_SSL
113  virtual void set_password_hash(const std::string& password_hash) {
115  // update password string representation
116  if (password_hash.size() == SHA256_DIGEST_LENGTH * 2) {
117  m_password_hash_type = SHA_256;
118  } else if (password_hash.size() == SHA_DIGEST_LENGTH * 2) {
119  m_password_hash_type = SHA_1;
120  } else {
121  BOOST_THROW_EXCEPTION( error::bad_password_hash() );
122  }
123  m_password = password_hash;
124 
125  // convert string from hex to binary value
126  char buf[3];
127  buf[2] = '\0';
128  unsigned int hash_pos = 0;
129  std::string::iterator str_it = m_password.begin();
130  while (str_it != m_password.end()) {
131  buf[0] = *str_it;
132  ++str_it;
133  buf[1] = *str_it;
134  ++str_it;
135  m_password_hash[hash_pos++] = boost::numeric_cast<unsigned char>(strtoul(buf, 0, 16));
136  }
137  }
138 #endif
139 
140 
141 protected:
142 
144  const std::string m_username;
145 
147  std::string m_password;
148 
149 #ifdef PION_HAVE_SSL
150  enum password_hash_type_t {EMPTY, SHA_1, SHA_256};
151 
153  password_hash_type_t m_password_hash_type;
154 
156  unsigned char m_password_hash[SHA256_DIGEST_LENGTH];
157 #endif
158 };
159 
161 typedef boost::shared_ptr<user> user_ptr;
162 
163 
168  private boost::noncopyable
169 {
170 public:
171 
173  user_manager(void) {}
174 
176  virtual ~user_manager() {}
177 
179  inline bool empty(void) const {
180  boost::mutex::scoped_lock lock(m_mutex);
181  return m_users.empty();
182  }
183 
192  virtual bool add_user(const std::string &username,
193  const std::string &password)
194  {
195  boost::mutex::scoped_lock lock(m_mutex);
196  user_map_t::iterator i = m_users.find(username);
197  if (i!=m_users.end())
198  return false;
199  user_ptr user_ptr(new user(username, password));
200  m_users.insert(std::make_pair(username, user_ptr));
201  return true;
202  }
203 
212  virtual bool update_user(const std::string &username,
213  const std::string &password)
214  {
215  boost::mutex::scoped_lock lock(m_mutex);
216  user_map_t::iterator i = m_users.find(username);
217  if (i==m_users.end())
218  return false;
219  i->second->set_password(password);
220  return true;
221  }
222 
223 #ifdef PION_HAVE_SSL
224 
232  virtual bool add_user_hash(const std::string &username,
233  const std::string &password_hash)
234  {
235  boost::mutex::scoped_lock lock(m_mutex);
236  user_map_t::iterator i = m_users.find(username);
237  if (i!=m_users.end())
238  return false;
239  user_ptr user_ptr(new user(username));
240  user_ptr->set_password_hash(password_hash);
241  m_users.insert(std::make_pair(username, user_ptr));
242  return true;
243  }
244 
253  virtual bool update_user_hash(const std::string &username,
254  const std::string &password_hash)
255  {
256  boost::mutex::scoped_lock lock(m_mutex);
257  user_map_t::iterator i = m_users.find(username);
258  if (i==m_users.end())
259  return false;
260  i->second->set_password_hash(password_hash);
261  return true;
262  }
263 #endif
264 
270  virtual bool remove_user(const std::string &username) {
271  boost::mutex::scoped_lock lock(m_mutex);
272  user_map_t::iterator i = m_users.find(username);
273  if (i==m_users.end())
274  return false;
275  m_users.erase(i);
276  return true;
277  }
278 
282  virtual user_ptr get_user(const std::string &username) {
283  boost::mutex::scoped_lock lock(m_mutex);
284  user_map_t::const_iterator i = m_users.find(username);
285  if (i==m_users.end())
286  return user_ptr();
287  else
288  return i->second;
289  }
290 
294  virtual user_ptr get_user(const std::string& username, const std::string& password) {
295  boost::mutex::scoped_lock lock(m_mutex);
296  user_map_t::const_iterator i = m_users.find(username);
297  if (i==m_users.end() || !i->second->match_password(password))
298  return user_ptr();
299  else
300  return i->second;
301  }
302 
303 
304 protected:
305 
307  typedef std::map<std::string, user_ptr> user_map_t;
308 
309 
311  mutable boost::mutex m_mutex;
312 
314  user_map_t m_users;
315 };
316 
318 typedef boost::shared_ptr<user_manager> user_manager_ptr;
319 
320 
321 } // end namespace pion
322 
323 #endif
std::string m_password
password string (actual contents depends on implementation)
Definition: user.hpp:147
virtual bool update_user(const std::string &username, const std::string &password)
Definition: user.hpp:212
virtual bool remove_user(const std::string &username)
Definition: user.hpp:270
virtual bool match_password(const std::string &password) const
Definition: user.hpp:76
std::string const & get_username() const
returns user name as a string
Definition: user.hpp:66
virtual ~user()
virtual destructor
Definition: user.hpp:63
bool empty(void) const
returns true if no users are defined
Definition: user.hpp:179
boost::mutex m_mutex
mutex used to protect access to the user list
Definition: user.hpp:311
user_manager(void)
construct a new user_manager object
Definition: user.hpp:173
virtual bool add_user(const std::string &username, const std::string &password)
Definition: user.hpp:192
user(std::string const &username, std::string const &password)
construct a new user object
Definition: user.hpp:53
std::string const & get_password() const
returns password for the user (encrypted if SSL is enabled)
Definition: user.hpp:69
virtual user_ptr get_user(const std::string &username, const std::string &password)
Definition: user.hpp:294
std::map< std::string, user_ptr > user_map_t
data type for a map of usernames to user objects
Definition: user.hpp:307
virtual void set_password(const std::string &password)
sets password credentials for given user
Definition: user.hpp:94
user(std::string const &username)
construct a new user object
Definition: user.hpp:45
const std::string m_username
username string
Definition: user.hpp:144
virtual user_ptr get_user(const std::string &username)
Definition: user.hpp:282
virtual ~user_manager()
virtual destructor
Definition: user.hpp:176
user_map_t m_users
user records container
Definition: user.hpp:314