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  {}
48 
50  user(std::string const &username, std::string const &password) :
51  m_username(username)
52  {
53  set_password(password);
54  }
55 
57  virtual ~user() {}
58 
60  std::string const & get_username() const { return m_username; }
61 
63  std::string const & get_password() const { return m_password; }
64 
70  virtual bool match_password(const std::string& password) const {
71 #ifdef PION_HAVE_SSL
72  unsigned char sha1_hash[SHA_DIGEST_LENGTH];
73  SHA1(reinterpret_cast<const unsigned char *>(password.data()), password.size(), sha1_hash);
74  return (memcmp(sha1_hash, m_password_hash, SHA_DIGEST_LENGTH) == 0);
75 #else
76  return m_password == password;
77 #endif
78  }
79 
81  virtual void set_password(const std::string& password) {
82 #ifdef PION_HAVE_SSL
83  // store encrypted hash value
84  SHA1((const unsigned char *)password.data(), password.size(), m_password_hash);
85 
86  // update password string (convert binary to hex)
87  m_password.clear();
88  char buf[3];
89  for (unsigned int n = 0; n < SHA_DIGEST_LENGTH; ++n) {
90  sprintf(buf, "%.2x", static_cast<unsigned int>(m_password_hash[n]));
91  m_password += buf;
92  }
93 #else
94  m_password = password;
95 #endif
96  }
97 
98 #ifdef PION_HAVE_SSL
99  virtual void set_password_hash(const std::string& password_hash) {
101  // update password string representation
102  if (password_hash.size() != SHA_DIGEST_LENGTH*2)
103  BOOST_THROW_EXCEPTION( error::bad_password_hash() );
104  m_password = password_hash;
105 
106  // convert string from hex to binary value
107  char buf[3];
108  buf[2] = '\0';
109  unsigned int hash_pos = 0;
110  std::string::iterator str_it = m_password.begin();
111  while (str_it != m_password.end()) {
112  buf[0] = *str_it;
113  ++str_it;
114  buf[1] = *str_it;
115  ++str_it;
116  m_password_hash[hash_pos++] = boost::numeric_cast<unsigned char>(strtoul(buf, 0, 16));
117  }
118  }
119 #endif
120 
121 
122 protected:
123 
125  const std::string m_username;
126 
128  std::string m_password;
129 
130 #ifdef PION_HAVE_SSL
131  unsigned char m_password_hash[SHA_DIGEST_LENGTH];
133 #endif
134 };
135 
137 typedef boost::shared_ptr<user> user_ptr;
138 
139 
144  private boost::noncopyable
145 {
146 public:
147 
149  user_manager(void) {}
150 
152  virtual ~user_manager() {}
153 
155  inline bool empty(void) const {
156  boost::mutex::scoped_lock lock(m_mutex);
157  return m_users.empty();
158  }
159 
168  virtual bool add_user(const std::string &username,
169  const std::string &password)
170  {
171  boost::mutex::scoped_lock lock(m_mutex);
172  user_map_t::iterator i = m_users.find(username);
173  if (i!=m_users.end())
174  return false;
175  user_ptr user_ptr(new user(username, password));
176  m_users.insert(std::make_pair(username, user_ptr));
177  return true;
178  }
179 
188  virtual bool update_user(const std::string &username,
189  const std::string &password)
190  {
191  boost::mutex::scoped_lock lock(m_mutex);
192  user_map_t::iterator i = m_users.find(username);
193  if (i==m_users.end())
194  return false;
195  i->second->set_password(password);
196  return true;
197  }
198 
199 #ifdef PION_HAVE_SSL
200 
208  virtual bool add_user_hash(const std::string &username,
209  const std::string &password_hash)
210  {
211  boost::mutex::scoped_lock lock(m_mutex);
212  user_map_t::iterator i = m_users.find(username);
213  if (i!=m_users.end())
214  return false;
215  user_ptr user_ptr(new user(username));
216  user_ptr->set_password_hash(password_hash);
217  m_users.insert(std::make_pair(username, user_ptr));
218  return true;
219  }
220 
229  virtual bool update_user_hash(const std::string &username,
230  const std::string &password_hash)
231  {
232  boost::mutex::scoped_lock lock(m_mutex);
233  user_map_t::iterator i = m_users.find(username);
234  if (i==m_users.end())
235  return false;
236  i->second->set_password_hash(password_hash);
237  return true;
238  }
239 #endif
240 
246  virtual bool remove_user(const std::string &username) {
247  boost::mutex::scoped_lock lock(m_mutex);
248  user_map_t::iterator i = m_users.find(username);
249  if (i==m_users.end())
250  return false;
251  m_users.erase(i);
252  return true;
253  }
254 
258  virtual user_ptr get_user(const std::string &username) {
259  boost::mutex::scoped_lock lock(m_mutex);
260  user_map_t::const_iterator i = m_users.find(username);
261  if (i==m_users.end())
262  return user_ptr();
263  else
264  return i->second;
265  }
266 
270  virtual user_ptr get_user(const std::string& username, const std::string& password) {
271  boost::mutex::scoped_lock lock(m_mutex);
272  user_map_t::const_iterator i = m_users.find(username);
273  if (i==m_users.end() || !i->second->match_password(password))
274  return user_ptr();
275  else
276  return i->second;
277  }
278 
279 
280 protected:
281 
283  typedef std::map<std::string, user_ptr> user_map_t;
284 
285 
287  mutable boost::mutex m_mutex;
288 
290  user_map_t m_users;
291 };
292 
294 typedef boost::shared_ptr<user_manager> user_manager_ptr;
295 
296 
297 } // end namespace pion
298 
299 #endif
std::string m_password
password string (actual contents depends on implementation)
Definition: user.hpp:128
virtual bool update_user(const std::string &username, const std::string &password)
Definition: user.hpp:188
virtual bool remove_user(const std::string &username)
Definition: user.hpp:246
virtual bool match_password(const std::string &password) const
Definition: user.hpp:70
std::string const & get_username() const
returns user name as a string
Definition: user.hpp:60
virtual ~user()
virtual destructor
Definition: user.hpp:57
bool empty(void) const
returns true if no users are defined
Definition: user.hpp:155
boost::mutex m_mutex
mutex used to protect access to the user list
Definition: user.hpp:287
user_manager(void)
construct a new user_manager object
Definition: user.hpp:149
virtual bool add_user(const std::string &username, const std::string &password)
Definition: user.hpp:168
user(std::string const &username, std::string const &password)
construct a new user object
Definition: user.hpp:50
exception thrown if a bad password hash is provided
Definition: error.hpp:209
std::string const & get_password() const
returns password for the user (encrypted if SSL is enabled)
Definition: user.hpp:63
virtual user_ptr get_user(const std::string &username, const std::string &password)
Definition: user.hpp:270
std::map< std::string, user_ptr > user_map_t
data type for a map of usernames to user objects
Definition: user.hpp:283
virtual void set_password(const std::string &password)
sets password credentials for given user
Definition: user.hpp:81
user(std::string const &username)
construct a new user object
Definition: user.hpp:45
const std::string m_username
username string
Definition: user.hpp:125
virtual user_ptr get_user(const std::string &username)
Definition: user.hpp:258
virtual ~user_manager()
virtual destructor
Definition: user.hpp:152
user_map_t m_users
user records container
Definition: user.hpp:290