~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/auth_ldap/auth_ldap.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include "config.h"
 
20
#include <config.h>
21
21
 
22
22
/* This is needed for simple auth, we're not ready for SASL yet. */
23
23
#define LDAP_DEPRECATED 1
28
28
#include <map>
29
29
#include <string>
30
30
 
31
 
#include "drizzled/plugin/authentication.h"
32
 
#include "drizzled/security_context.h"
33
 
#include "drizzled/util/convert.h"
34
 
#include "drizzled/algorithm/sha1.h"
35
 
 
 
31
#include <drizzled/plugin/authentication.h>
 
32
#include <drizzled/identifier.h>
 
33
#include <drizzled/util/convert.h>
 
34
#include <drizzled/algorithm/sha1.h>
 
35
 
 
36
#include <drizzled/module/option_map.h>
 
37
#include <boost/program_options.hpp>
 
38
 
 
39
namespace po= boost::program_options;
36
40
using namespace std;
37
41
using namespace drizzled;
38
42
 
39
43
namespace auth_ldap
40
44
{
41
45
 
42
 
static char *uri= NULL;
43
 
static const char DEFAULT_URI[]= "ldap://127.0.0.1/";
44
 
static char *bind_dn= NULL;
45
 
static char *bind_password= NULL;
46
 
static char *base_dn= NULL;
47
 
static char *password_attribute= NULL;
48
 
static const char DEFAULT_PASSWORD_ATTRIBUTE[]= "userPassword";
49
 
static char *mysql_password_attribute= NULL;
50
 
static const char DEFAULT_MYSQL_PASSWORD_ATTRIBUTE[]= "mysqlUserPassword";
51
 
static int cache_timeout= 0;
 
46
std::string uri;
 
47
const std::string DEFAULT_URI= "ldap://127.0.0.1/";
 
48
std::string bind_dn;
 
49
std::string bind_password;
 
50
std::string base_dn;
 
51
std::string password_attribute;
 
52
std::string DEFAULT_PASSWORD_ATTRIBUTE= "userPassword";
 
53
std::string mysql_password_attribute;
 
54
const std::string DEFAULT_MYSQL_PASSWORD_ATTRIBUTE= "mysqlUserPassword";
52
55
static const int DEFAULT_CACHE_TIMEOUT= 600;
 
56
typedef constrained_check<int, DEFAULT_CACHE_TIMEOUT, 0, 2147483647> cachetimeout_constraint;
 
57
static cachetimeout_constraint cache_timeout= 0;
 
58
 
53
59
 
54
60
class AuthLDAP: public plugin::Authentication
55
61
{
86
92
    MYSQL_HASH
87
93
  } PasswordType;
88
94
 
89
 
  typedef pair<PasswordType, string> PasswordEntry;
90
 
  typedef pair<string, PasswordEntry> UserEntry;
91
 
  typedef map<string, PasswordEntry> UserCache;
 
95
  typedef std::pair<PasswordType, std::string> PasswordEntry;
 
96
  typedef std::pair<std::string, PasswordEntry> UserEntry;
 
97
  typedef std::map<std::string, PasswordEntry> UserCache;
92
98
 
93
99
  /**
94
100
   * Base class method to check authentication for a user.
95
101
   */
96
 
  bool authenticate(const SecurityContext &sctx, const string &password);
 
102
  bool authenticate(const identifier::User &sctx, const string &password);
97
103
 
98
104
  /**
99
105
   * Lookup a user in LDAP.
154
160
 
155
161
bool AuthLDAP::connect(void)
156
162
{
157
 
  int return_code= ldap_initialize(&ldap, uri);
 
163
  int return_code= ldap_initialize(&ldap, (char *)uri.c_str());
158
164
  if (return_code != LDAP_SUCCESS)
159
165
  {
160
166
    error= "ldap_initialize failed: ";
173
179
    return false;
174
180
  }
175
181
 
176
 
  if (bind_dn != NULL)
 
182
  if (not bind_dn.empty())
177
183
  {
178
 
    return_code= ldap_simple_bind_s(ldap, bind_dn, bind_password);
 
184
    return_code= ldap_simple_bind_s(ldap, (char *)bind_dn.c_str(), (char *)bind_password.c_str());
179
185
    if (return_code != LDAP_SUCCESS)
180
186
    {
181
187
      ldap_unbind(ldap);
194
200
  return error;
195
201
}
196
202
 
197
 
bool AuthLDAP::authenticate(const SecurityContext &sctx, const string &password)
 
203
bool AuthLDAP::authenticate(const identifier::User &sctx, const string &password)
198
204
{
199
205
  /* See if cache should be emptied. */
200
206
  if (cache_timeout > 0)
216
222
 
217
223
  pthread_rwlock_rdlock(&lock);
218
224
 
219
 
  AuthLDAP::UserCache::const_iterator user= users.find(sctx.getUser());
 
225
  AuthLDAP::UserCache::const_iterator user= users.find(sctx.username());
220
226
  if (user == users.end())
221
227
  {
222
228
    pthread_rwlock_unlock(&lock);
224
230
    pthread_rwlock_wrlock(&lock);
225
231
 
226
232
    /* Make sure the user was not added while we unlocked. */
227
 
    user= users.find(sctx.getUser());
 
233
    user= users.find(sctx.username());
228
234
    if (user == users.end())
229
 
      lookupUser(sctx.getUser());
 
235
      lookupUser(sctx.username());
230
236
 
231
237
    pthread_rwlock_unlock(&lock);
232
238
 
233
239
    pthread_rwlock_rdlock(&lock);
234
240
 
235
241
    /* Get user again because map may have changed while unlocked. */
236
 
    user= users.find(sctx.getUser());
 
242
    user= users.find(sctx.username());
237
243
    if (user == users.end())
238
244
    {
239
245
      pthread_rwlock_unlock(&lock);
247
253
    return false;
248
254
  }
249
255
 
250
 
  if (sctx.getPasswordType() == SecurityContext::MYSQL_HASH)
 
256
  if (sctx.getPasswordType() == identifier::User::MYSQL_HASH)
251
257
  {
252
258
    bool allow= verifyMySQLHash(user->second, sctx.getPasswordContext(), password);
253
259
    pthread_rwlock_unlock(&lock);
269
275
  string filter("(cn=" + user + ")");
270
276
  const char *attributes[3]=
271
277
  {
272
 
    password_attribute,
273
 
    mysql_password_attribute,
 
278
    (char *)password_attribute.c_str(),
 
279
    (char *)mysql_password_attribute.c_str(),
274
280
    NULL
275
281
  };
276
282
  LDAPMessage *result;
282
288
    {
283
289
      if (! connect())
284
290
      {
285
 
        errmsg_printf(ERRMSG_LVL_ERROR, _("Reconnect failed: %s\n"),
 
291
        errmsg_printf(error::ERROR, _("Reconnect failed: %s\n"),
286
292
                      getError().c_str());
287
293
        return;
288
294
      }
289
295
    }
290
296
 
291
297
    int return_code= ldap_search_ext_s(ldap,
292
 
                                       base_dn,
 
298
                                       (char *)base_dn.c_str(),
293
299
                                       LDAP_SCOPE_ONELEVEL,
294
300
                                       filter.c_str(),
295
301
                                       const_cast<char **>(attributes),
301
307
                                       &result);
302
308
    if (return_code != LDAP_SUCCESS)
303
309
    {
304
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("ldap_search_ext_s failed: %s\n"),
 
310
      errmsg_printf(error::ERROR, _("ldap_search_ext_s failed: %s\n"),
305
311
                    ldap_err2string(return_code));
306
312
 
307
313
      /* Only try one reconnect per request. */
325
331
    new_password= AuthLDAP::PasswordEntry(NOT_FOUND, "");
326
332
  else
327
333
  {
328
 
    char **values= ldap_get_values(ldap, entry, mysql_password_attribute);
 
334
    char **values= ldap_get_values(ldap, entry, (char *)mysql_password_attribute.c_str());
329
335
    if (values == NULL)
330
336
    {
331
 
      values= ldap_get_values(ldap, entry, password_attribute);
 
337
      values= ldap_get_values(ldap, entry, (char *)password_attribute.c_str());
332
338
      if (values == NULL)
333
339
        new_password= AuthLDAP::PasswordEntry(NOT_FOUND, "");
334
340
      else
407
413
  AuthLDAP *auth_ldap= new AuthLDAP("auth_ldap");
408
414
  if (! auth_ldap->initialize())
409
415
  {
410
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Could not load auth ldap: %s\n"),
 
416
    errmsg_printf(error::ERROR, _("Could not load auth ldap: %s\n"),
411
417
                  auth_ldap->getError().c_str());
412
418
    delete auth_ldap;
413
419
    return 1;
414
420
  }
415
421
 
 
422
  context.registerVariable(new sys_var_const_string_val("uri", uri));
 
423
  context.registerVariable(new sys_var_const_string_val("bind-dn", bind_dn));
 
424
  context.registerVariable(new sys_var_const_string_val("bind-password", bind_password));
 
425
  context.registerVariable(new sys_var_const_string_val("base-dn", base_dn));
 
426
  context.registerVariable(new sys_var_const_string_val("password-attribute",password_attribute));
 
427
  context.registerVariable(new sys_var_const_string_val("mysql-password-attribute", mysql_password_attribute));
 
428
  context.registerVariable(new sys_var_constrained_value_readonly<int>("cache-timeout", cache_timeout));
 
429
 
416
430
  context.add(auth_ldap);
417
431
  return 0;
418
432
}
419
433
 
420
 
static DRIZZLE_SYSVAR_STR(uri,
421
 
                          uri,
422
 
                          PLUGIN_VAR_READONLY,
423
 
                          N_("URI of the LDAP server to contact"),
424
 
                          NULL, /* check func */
425
 
                          NULL, /* update func*/
426
 
                          DEFAULT_URI);
427
 
 
428
 
static DRIZZLE_SYSVAR_STR(bind_dn,
429
 
                          bind_dn,
430
 
                          PLUGIN_VAR_READONLY,
431
 
                          N_("DN to use when binding to the LDAP server"),
432
 
                          NULL, /* check func */
433
 
                          NULL, /* update func*/
434
 
                          NULL); /* default value */
435
 
 
436
 
static DRIZZLE_SYSVAR_STR(bind_password,
437
 
                          bind_password,
438
 
                          PLUGIN_VAR_READONLY,
439
 
                          N_("Password to use when binding the DN"),
440
 
                          NULL, /* check func */
441
 
                          NULL, /* update func*/
442
 
                          NULL); /* default value */
443
 
 
444
 
static DRIZZLE_SYSVAR_STR(base_dn,
445
 
                          base_dn,
446
 
                          PLUGIN_VAR_READONLY,
447
 
                          N_("DN to use when searching"),
448
 
                          NULL, /* check func */
449
 
                          NULL, /* update func*/
450
 
                          NULL); /* default value */
451
 
 
452
 
static DRIZZLE_SYSVAR_STR(password_attribute,
453
 
                          password_attribute,
454
 
                          PLUGIN_VAR_READONLY,
455
 
                          N_("Attribute in LDAP with plain text password"),
456
 
                          NULL, /* check func */
457
 
                          NULL, /* update func*/
458
 
                          DEFAULT_PASSWORD_ATTRIBUTE);
459
 
 
460
 
static DRIZZLE_SYSVAR_STR(mysql_password_attribute,
461
 
                          mysql_password_attribute,
462
 
                          PLUGIN_VAR_READONLY,
463
 
                          N_("Attribute in LDAP with MySQL hashed password"),
464
 
                          NULL, /* check func */
465
 
                          NULL, /* update func*/
466
 
                          DEFAULT_MYSQL_PASSWORD_ATTRIBUTE);
467
 
 
468
 
static DRIZZLE_SYSVAR_INT(cache_timeout,
469
 
                          cache_timeout,
470
 
                          PLUGIN_VAR_READONLY,
471
 
                          N_("How often to empty the users cache, 0 to disable"),
472
 
                          NULL, /* check func */
473
 
                          NULL, /* update func */
474
 
                          DEFAULT_CACHE_TIMEOUT,
475
 
                          0,
476
 
                          2147483647,
477
 
                          0);
478
 
 
479
 
static drizzle_sys_var* sys_variables[]=
 
434
static void init_options(drizzled::module::option_context &context)
480
435
{
481
 
  DRIZZLE_SYSVAR(uri),
482
 
  DRIZZLE_SYSVAR(bind_dn),
483
 
  DRIZZLE_SYSVAR(bind_password),
484
 
  DRIZZLE_SYSVAR(base_dn),
485
 
  DRIZZLE_SYSVAR(password_attribute),
486
 
  DRIZZLE_SYSVAR(mysql_password_attribute),
487
 
  DRIZZLE_SYSVAR(cache_timeout),
488
 
  NULL
489
 
};
 
436
  context("uri", po::value<string>(&uri)->default_value(DEFAULT_URI),
 
437
          N_("URI of the LDAP server to contact"));
 
438
  context("bind-db", po::value<string>(&bind_dn)->default_value(""),
 
439
          N_("DN to use when binding to the LDAP server"));
 
440
  context("bind-password", po::value<string>(&bind_password)->default_value(""),
 
441
          N_("Password to use when binding the DN"));
 
442
  context("base-dn", po::value<string>(&base_dn)->default_value(""),
 
443
          N_("DN to use when searching"));
 
444
  context("password-attribute", po::value<string>(&password_attribute)->default_value(DEFAULT_PASSWORD_ATTRIBUTE),
 
445
          N_("Attribute in LDAP with plain text password"));
 
446
  context("mysql-password-attribute", po::value<string>(&mysql_password_attribute)->default_value(DEFAULT_MYSQL_PASSWORD_ATTRIBUTE),
 
447
          N_("Attribute in LDAP with MySQL hashed password"));
 
448
  context("cache-timeout", po::value<cachetimeout_constraint>(&cache_timeout)->default_value(DEFAULT_CACHE_TIMEOUT),
 
449
          N_("How often to empty the users cache, 0 to disable"));
 
450
}
490
451
 
491
452
} /* namespace auth_ldap */
492
453
 
493
 
DRIZZLE_PLUGIN(auth_ldap::init, auth_ldap::sys_variables, NULL);
 
454
DRIZZLE_PLUGIN(auth_ldap::init, NULL, auth_ldap::init_options);