RSS

(root)/mod_ldap/head : /mod_ldap.c (revision 88)

Line Revision Contents
1 20
/*
2
 * mod_ldap - LDAP password lookup module for ProFTPD
3 62
 * Copyright (c) 1999, 2000-9, John Morrissey <jwm@horde.net>
4 8
 *
5 4
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
18 17
 *
19
 * Furthermore, John Morrissey gives permission to link this program with
20
 * OpenSSL, and distribute the resulting executable, without including the
21
 * source code for OpenSSL in the source distribution.
22 4
 */
23
24
/*
25 78
 * mod_ldap v2.9.0-pre0
26 13
 *
27
 * Thanks for patches go to (in alphabetical order):
28 18
 *
29 13
 * Peter Fabian (fabian at staff dot matavnet dot hu) - LDAPAuthBinds
30 23
 * Alexandre Francois (alexandre-francois at voila dot fr) - LDAPAliasDereference
31 20
 * Marek Gradzki (mgradzki at ost dot net dot pl) - LDAPProtocolVersion
32 13
 * Pierrick Hascoet (pierrick at alias dot fr) - OpenSSL password hash support
33
 * Florian Lohoff (flo at rfc822 dot org) - LDAPForceDefault[UG]ID code
34
 * Steve Luzynski (steve at uniteone dot net) - HomedirOnDemandPrefix support
35
 * Gaute Nessan (gaute at kpnqwest dot no) - OpenLDAP 2.0 fixes
36
 * Marcin Obara (gryzzli at wp-sa dot pl) - User/group caching code, Sun
37
 *                                          LDAP library portability fixes
38 19
 * Phil Oester (phil at theoesters dot com) - Group code memory manip fixes
39 13
 * Michael Schout (mschout at gkg dot net) - Full-path HomedirOnDemand and
40
 *                                           multiple-HomedirOnDemandSuffix
41
 *                                           support
42 18
 * Klaus Steinberger (klaus dot steinberger at physik dot uni-muenchen dot de)
43
 *                                         - LDAPForceHomedirOnDemand support
44 16
 * Andreas Strodl (andreas at strodl dot org) - multiple group support
45 13
 * Ross Thomas (ross at grinfinity dot com) - Non-AuthBinds auth fix
46 16
 * Ivo Timmermans (ivo at debian dot org) - TLS support
47 13
 * Bert Vermeulen (bert at be dot easynet dot net) - LDAPHomedirOnDemand,
48
 *                                                   LDAPDefaultAuthScheme
49
 *
50 18
 *
51 64
 * $Id$
52 4
 * $Libraries: -lldap -llber$
53 27
 */
54
55
/* To verify non-crypt() password hashes locally with OpenSSL, build ProFTPD
56
 * with the --enable-openssl argument to configure.
57 13
 */
58
59 4
#include "conf.h"
60 13
#include "privs.h"
61 4
62 71
#define MOD_LDAP_VERSION	"mod_ldap/2.9.0-pre"
63 20
64 86
#if PROFTPD_VERSION_NUMBER < 0x0001030103
65
# error MOD_LDAP_VERSION " requires ProFTPD 1.3.1rc3 or later"
66 20
#endif
67
68
#if defined(HAVE_CRYPT_H) && !defined(AIX4) && !defined(AIX5)
69 13
# include <crypt.h>
70 4
#endif
71
72 71
#include <ctype.h> /* isdigit()   */
73 11
#include <errno.h>
74 16
75 4
#include <lber.h>
76
#include <ldap.h>
77 36
78 85
#if LDAP_API_VERSION >= 2000
79
# define HAS_LDAP_SASL_BIND_S
80
#endif
81
82 65
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_VENDOR_VERSION >= 192)
83 85
# define HAS_LDAP_UNBIND_EXT_S
84
#endif
85
86
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_VENDOR_VERSION >= 19905)
87
# define HAS_LDAP_INITIALIZE
88
#endif
89
90
#ifdef HAS_LDAP_UNBIND_EXT_S
91 65
# define LDAP_UNBIND(ld) (ldap_unbind_ext_s(ld, NULL, NULL))
92
#else
93
# define LDAP_UNBIND(ld) (ldap_unbind_s(ld))
94 68
static char *ldap_server;
95
static int ldap_port = LDAP_PORT;
96 65
#endif
97
98 36
#if LDAP_API_VERSION >= 2000
99
# define LDAP_VALUE_T struct berval
100
# define LDAP_GET_VALUES(ld, entry, attr) ldap_get_values_len(ld, entry, attr)
101
# define LDAP_VALUE(values, i) (values[i]->bv_val)
102
# define LDAP_COUNT_VALUES(values) (ldap_count_values_len(values))
103
# define LDAP_VALUE_FREE(values) (ldap_value_free_len(values))
104
# define LDAP_SEARCH(ld, base, scope, filter, attrs, timeout, sizelimit, res) \
105
   ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, \
106
                     timeout, sizelimit, res)
107 47
#else /* LDAP_API_VERSION >= 2000 */
108 36
# define LDAP_VALUE_T char
109
# define LDAP_GET_VALUES(ld, entry, attr) ldap_get_values(ld, entry, attr)
110
# define LDAP_VALUE(values, i) (values[i])
111
# define LDAP_COUNT_VALUES(values) (ldap_count_values(values))
112
# define LDAP_VALUE_FREE(values) (ldap_value_free(values))
113
114
static void
115
pr_ldap_set_sizelimit(LDAP *limit_ld, int limit)
116
{
117
#ifdef LDAP_OPT_SIZELIMIT
118
  int ret;
119
  if ((ret = ldap_set_option(limit_ld, LDAP_OPT_SIZELIMIT, (void *)&limit)) != LDAP_OPT_SUCCESS) {
120
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_set_sizelimit(): ldap_set_option() unable to set query size limit to %d entries: %s", limit, ldap_err2string(ret));
121
  }
122
#else
123
  limit_ld->ld_sizelimit = limit;
124
#endif
125
126
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": set search size limit to %d", limit);
127
}
128
129 47
static int
130
LDAP_SEARCH(LDAP *ld, char *base, int scope, char *filter, char *attrs[],
131
            struct timeval *timeout, int sizelimit, LDAPMessage **res)
132
{
133
  pr_ldap_set_sizelimit(ld, sizelimit);
134
  return ldap_search_st(ld, base, scope, filter, attrs, 0, timeout, res);
135
}
136
#endif /* LDAP_API_VERSION >= 2000 */
137 4
138 20
/* Thanks, Sun. */
139 13
#ifndef LDAP_OPT_SUCCESS
140
# define LDAP_OPT_SUCCESS LDAP_SUCCESS
141
#endif
142 77
#ifndef LDAP_URL_SUCCESS
143
# define LDAP_URL_SUCCESS LDAP_SUCCESS
144
#endif
145 48
#ifndef LDAP_SCOPE_DEFAULT
146
# define LDAP_SCOPE_DEFAULT LDAP_SCOPE_SUBTREE
147
#endif
148 13
149 31
#if defined(HAVE_OPENSSL) || defined(PR_USE_OPENSSL)
150 13
# include <openssl/evp.h>
151 8
#endif
152
153 4
/* Config entries */
154 77
static array_header *ldap_servers = NULL;
155
static unsigned int cur_server_index = 0;
156
static char *ldap_dn, *ldap_dnpass,
157 16
            *ldap_auth_filter, *ldap_uid_filter,
158
            *ldap_group_gid_filter, *ldap_group_name_filter,
159 18
            *ldap_group_member_filter, *ldap_quota_filter,
160 13
            *ldap_auth_basedn, *ldap_uid_basedn, *ldap_gid_basedn,
161 18
            *ldap_quota_basedn,
162 13
            *ldap_defaultauthscheme, *ldap_authbind_dn,
163 20
            *ldap_genhdir_prefix, *ldap_default_quota,
164
            *ldap_attr_uid = "uid",
165
            *ldap_attr_uidnumber = "uidNumber",
166
            *ldap_attr_gidnumber = "gidNumber",
167
            *ldap_attr_homedirectory = "homeDirectory",
168
            *ldap_attr_userpassword = "userPassword",
169
            *ldap_attr_loginshell = "loginShell",
170
            *ldap_attr_cn = "cn",
171
            *ldap_attr_memberuid = "memberUid",
172
            *ldap_attr_ftpquota = "ftpQuota";
173 85
#ifdef HAS_LDAP_INITIALIZE
174 77
static char *ldap_server_url;
175 85
#endif /* HAS_LDAP_INITIALIZE */
176 53
static int ldap_doauth = 0, ldap_douid = 0, ldap_dogid = 0, ldap_doquota = 0,
177 43
           ldap_authbinds = 1, ldap_querytimeout = 0,
178
           ldap_genhdir = 0, ldap_genhdir_prefix_nouname = 0,
179 13
           ldap_forcedefaultuid = 0, ldap_forcedefaultgid = 0,
180 20
           ldap_forcegenhdir = 0, ldap_protocol_version = 3,
181 23
           ldap_dereference = LDAP_DEREF_NEVER,
182 13
           ldap_search_scope = LDAP_SCOPE_SUBTREE;
183
static struct timeval ldap_querytimeout_tp;
184
185
static uid_t ldap_defaultuid = -1;
186
static gid_t ldap_defaultgid = -1;
187
188 51
#ifdef LDAP_OPT_X_TLS
189 13
static int ldap_use_tls = 0;
190
#endif
191
192 20
static LDAP *ld = NULL;
193 82
static array_header *cached_quota = NULL;
194 13
195
196
static void
197 19
pr_ldap_unbind(void)
198
{
199
  int ret;
200
201 26
  if (!ld) {
202 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": not unbinding to an already unbound connection.");
203 19
    return;
204 26
  }
205
206 36
  ret = LDAP_UNBIND(ld);
207
  if (ret != LDAP_SUCCESS) {
208
    pr_log_pri(PR_LOG_NOTICE, MOD_LDAP_VERSION ": pr_ldap_unbind(): unbind failed: %s", ldap_err2string(ret));
209 71
  } else {
210
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": successfully unbound");
211 32
  }
212 19
213
  ld = NULL;
214
}
215
216 13
static int
217 77
_ldap_connect(LDAP **conn_ld, int do_bind)
218 13
{
219 23
  int ret, version;
220 85
#ifdef HAS_LDAP_SASL_BIND_S
221 36
  struct berval bindcred;
222
#endif
223
224 85
#ifdef HAS_LDAP_INITIALIZE
225 77
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": attempting connection to %s", ldap_server_url);
226
227 53
  ret = ldap_initialize(conn_ld, ldap_server_url);
228
  if (ret != LDAP_SUCCESS) {
229
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): ldap_initialize() to %s failed: %s", ldap_server_url, ldap_err2string(ret));
230 77
    ++cur_server_index;
231
    if (cur_server_index >= ldap_servers->nelts) {
232
      cur_server_index = 0;
233
    }
234 53
    *conn_ld = NULL;
235
    return -1;
236
  }
237 85
#else /* HAS_LDAP_INITIALIZE */
238 77
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": attempting connection to %s:%d", ldap_server, ldap_port);
239
240 37
  *conn_ld = ldap_init(ldap_server, ldap_port);
241 36
  if (!conn_ld) {
242 53
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): ldap_init() to %s:%d failed: %s", ldap_server, ldap_port, strerror(errno));
243 13
    return -1;
244
  }
245 85
#endif /* HAS_LDAP_INITIALIZE */
246 53
247 71
  version = LDAP_VERSION3;
248
  if (ldap_protocol_version == 2) {
249
    version = LDAP_VERSION2;
250 20
  }
251
252 36
  ret = ldap_set_option(*conn_ld, LDAP_OPT_PROTOCOL_VERSION, &version);
253
  if (ret != LDAP_OPT_SUCCESS) {
254 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): Setting LDAP version option failed: %s", ldap_err2string(ret));
255
    pr_ldap_unbind();
256
    return -1;
257
  }
258
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": set protocol version to %d", version);
259
260 85
#ifdef HAS_LDAP_INITIALIZE
261 77
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": connected to %s", ldap_server_url);
262 85
#else /* HAS_LDAP_INITIALIZE */
263 77
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": connected to %s:%d", ldap_server, ldap_port);
264 85
#endif /* HAS_LDAP_INITIALIZE */
265 77
266 51
#ifdef LDAP_OPT_X_TLS
267 32
  if (ldap_use_tls == 1) {
268 36
    ret = ldap_start_tls_s(*conn_ld, NULL, NULL);
269
    if (ret != LDAP_SUCCESS) {
270 32
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): Starting TLS failed: %s", ldap_err2string(ret));
271 20
      pr_ldap_unbind();
272
      return -1;
273
    }
274 37
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": enabled TLS.");
275 20
  }
276 51
#endif /* LDAP_OPT_X_TLS */
277 20
278 43
  if (do_bind == TRUE) {
279 85
#ifdef HAS_LDAP_SASL_BIND_S
280 36
    bindcred.bv_val = ldap_dnpass;
281 42
    bindcred.bv_len = ldap_dnpass != NULL ? strlen(ldap_dnpass) : 0;
282 36
    ret = ldap_sasl_bind_s(*conn_ld, ldap_dn, NULL, &bindcred, NULL, NULL, NULL);
283 85
#else /* HAS_LDAP_SASL_BIND_S */
284 36
    ret = ldap_simple_bind_s(*conn_ld, ldap_dn, ldap_dnpass);
285 85
#endif /* HAS_LDAP_SASL_BIND_S */
286 36
287
    if (ret != LDAP_SUCCESS) {
288
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): bind as %s failed: %s", ldap_dn, ldap_err2string(ret));
289 71
      pr_ldap_unbind();
290 20
      return -1;
291
    }
292 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": successfully bound as %s with password %s", ldap_dn, ldap_dnpass);
293 20
  }
294
295 37
#ifdef LDAP_OPT_DEREF
296
  ret = ldap_set_option(*conn_ld, LDAP_OPT_DEREF, (void *)&ldap_dereference);
297
  if (ret != LDAP_OPT_SUCCESS) {
298
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): ldap_set_option() unable to set dereference to %d: %s", ldap_dereference, ldap_err2string(ret));
299 71
    pr_ldap_unbind();
300
    return -1;
301 37
  }
302
#else
303
  deref_ld->ld_deref = ldap_dereference;
304
#endif
305
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": set dereferencing to %d", ldap_dereference);
306 4
307 11
  ldap_querytimeout_tp.tv_sec = (ldap_querytimeout > 0 ? ldap_querytimeout : 5);
308 8
  ldap_querytimeout_tp.tv_usec = 0;
309 88
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": set query timeout to %us", (unsigned)ldap_querytimeout_tp.tv_sec);
310 13
311
  return 1;
312
}
313
314 77
static int pr_ldap_connect(LDAP **conn_ld, int do_bind) {
315
  int start_server_index;
316
  char *item;
317
  LDAPURLDesc *url;
318
319
  if (!ldap_servers || ldap_servers->nelts == 0) {
320
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): internal error: no LDAP servers configured.");
321
    return -1;
322
  }
323
324
  start_server_index = cur_server_index;
325
  do {
326
    item = ((char **)ldap_servers->elts)[cur_server_index];
327
328
    /* item might be NULL if no LDAPServer directive was specified
329
     * and we're using the SDK default.
330
     */
331
    if (item) {
332
      if (ldap_is_ldap_url(item)) {
333
        if (ldap_url_parse(item, &url) != LDAP_URL_SUCCESS) {
334
          pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_connect(): url %s was valid during ProFTPD startup, but is no longer valid?!", item);
335
336
          ++cur_server_index;
337
          if (cur_server_index >= ldap_servers->nelts) {
338
            cur_server_index = 0;
339
          }
340
          continue;
341
        }
342
343 85
#ifdef HAS_LDAP_INITIALIZE
344 77
        ldap_server_url = item;
345 85
#else /* HAS_LDAP_INITIALIZE */
346 77
        /* Need to keep parsed host and port for pre-2000 ldap_init(). */
347
        if (url->lud_host != NULL) {
348
          ldap_server = pstrdup(session.pool, url->lud_host);
349
        }
350
        if (url->lud_port != 0) {
351
          ldap_port = url->lud_port;
352
        }
353 85
#endif /* HAS_LDAP_INITIALIZE */
354 77
355
        if (url->lud_scope != LDAP_SCOPE_DEFAULT) {
356
          ldap_search_scope = url->lud_scope;
357 81
          if (ldap_search_scope == LDAP_SCOPE_BASE) {
358
            pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": WARNING: LDAP URL search scopes default to 'base' (not 'sub') and may not be what you want.");
359
          }
360 77
        }
361
362
        ldap_free_urldesc(url);
363
      } else {
364 85
#ifdef HAS_LDAP_INITIALIZE
365 77
        ldap_server_url = pstrcat(session.pool, "ldap://", item, "/", NULL);
366 85
#else /* HAS_LDAP_INITIALIZE */
367 77
        ldap_server = pstrdup(session.pool, item);
368
        ldap_port = LDAP_PORT;
369 85
#endif /*  HAS_LDAP_INITIALIZE */
370 77
      }
371
    }
372
373
    if (_ldap_connect(conn_ld, do_bind) == 1) {
374
      return 1;
375
    }
376
377
    ++cur_server_index;
378
    if (cur_server_index >= ldap_servers->nelts) {
379
      cur_server_index = 0;
380
    }
381
  } while (cur_server_index != start_server_index);
382
383
  return -1;
384
}
385
386 17
static char *
387 72
pr_ldap_interpolate_filter(pool *p, char *template, const char *value)
388 17
{
389 73
  char *escaped_value, *filter;
390
391 79
  escaped_value = sreplace(p, (char *)value,
392 73
    "\\", "\\\\",
393
    "*", "\\*",
394
    "(", "\\(",
395
    ")", "\\)",
396
    NULL
397
  );
398
  if (!escaped_value) {
399
    return NULL;
400 72
  }
401
402 73
  filter = sreplace(p, template,
403
    "%u", escaped_value,
404
    "%v", escaped_value,
405
    NULL
406
  );
407
  if (!filter) {
408
    return NULL;
409 72
  }
410
411
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": generated filter %s from template %s and value %s", filter, template, value);
412 18
  return filter;
413 17
}
414
415 84
LDAPMessage *
416
pr_ldap_search(char *basedn, char *filter, char *ldap_attrs[], int sizelimit)
417
{
418
  int ret;
419
  LDAPMessage *result;
420
421
  if (!basedn) {
422
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": no LDAP base DN specified for auth/UID lookups, declining request.");
423
    return NULL;
424
  }
425
426
  /* If the LDAP connection has gone away or hasn't been established
427
   * yet, attempt to establish it now.
428
   */
429
  if (ld == NULL) {
430
    /* If we _still_ can't connect, give up and return NULL. */
431
    if (pr_ldap_connect(&ld, TRUE) == -1) {
432
      return NULL;
433
    }
434
  }
435
436
  ret = LDAP_SEARCH(ld, basedn, ldap_search_scope, filter, ldap_attrs,
437
    &ldap_querytimeout_tp, sizelimit, &result);
438
  if (ret != LDAP_SUCCESS) {
439
    if (ret == LDAP_SERVER_DOWN) {
440
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_search(): LDAP server went away, trying to reconnect");
441
442
      if (pr_ldap_connect(&ld, TRUE) == -1) {
443
        pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_search(): LDAP server went away, unable to reconnect");
444
        ld = NULL;
445
        return NULL;
446
      }
447
448
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_search(): Reconnect to LDAP server successful, resuming normal operations");
449
450
      ret = LDAP_SEARCH(ld, basedn, ldap_search_scope, filter, ldap_attrs,
451
        &ldap_querytimeout_tp, 2, &result);
452
      if (ret != LDAP_SUCCESS) {
453
        pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_search(): LDAP search failed: %s", ldap_err2string(ret));
454
        return NULL;
455
      }
456
    } else {
457
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_search(): LDAP search failed: %s", ldap_err2string(ret));
458
      return NULL;
459
    }
460
  }
461
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": searched under base DN %s using filter %s", basedn, filter);
462
463
  return result;
464
}
465
466 17
static struct passwd *
467
pr_ldap_user_lookup(pool *p,
468
                    char *filter_template, const char *replace,
469
                    char *basedn, char *ldap_attrs[],
470
                    char **user_dn)
471
{
472 36
  char *filter, *dn;
473 84
  int i = 0;
474 43
  struct passwd *pw;
475 4
  LDAPMessage *result, *e;
476 36
  LDAP_VALUE_T **values;
477 13
478 72
  filter = pr_ldap_interpolate_filter(p, filter_template, replace);
479 73
  if (!filter) {
480
    return NULL;
481
  }
482 13
483 84
  result = pr_ldap_search(basedn, filter, ldap_attrs, 2);
484
  if (result == NULL) {
485
    return NULL;
486 13
  }
487
488
  if (ldap_count_entries(ld, result) > 1) {
489 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): LDAP search returned multiple entries, aborting query");
490 17
    ldap_msgfree(result);
491 4
    return NULL;
492
  }
493
494 36
  e = ldap_first_entry(ld, result);
495
  if (!e) {
496 4
    ldap_msgfree(result);
497 74
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no entries for filter %s under base DN %s", filter, basedn);
498 4
    return NULL; /* No LDAP entries for this user */
499
  }
500
501 43
  pw = pcalloc(session.pool, sizeof(struct passwd));
502 4
  while (ldap_attrs[i] != NULL) {
503 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": fetching value(s) for attr %s", ldap_attrs[i]);
504
505 36
    values = LDAP_GET_VALUES(ld, e, ldap_attrs[i]);
506
    if (values == NULL) {
507 32
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no values for attribute %s, trying defaults...", ldap_attrs[i]);
508
509 13
      /* Try to fill in default values if there's no value for certain attrs. */
510 4
511 13
      /* If we can't find the [ug]idNumber attrs, just fill the passwd
512 4
         struct in with default values from the config file. */
513 20
      if (strcasecmp(ldap_attrs[i], ldap_attr_uidnumber) == 0) {
514 13
        if (ldap_defaultuid == -1) {
515 32
          pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): no %s attr for DN %s and LDAPDefaultUID was not specified!", (dn = ldap_get_dn(ld, e)), ldap_attr_uidnumber);
516 13
          free(dn);
517
          return NULL;
518
        }
519
520
        pw->pw_uid = ldap_defaultuid;
521
        ++i;
522 36
        pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": using default UID %lu", (unsigned long)pw->pw_uid);
523 13
        continue;
524
      }
525 20
      if (strcasecmp(ldap_attrs[i], ldap_attr_gidnumber) == 0) {
526 13
        if (ldap_defaultgid == -1) {
527 32
          pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): no %s attr for DN %s and LDAPDefaultGID was not specified!", (dn = ldap_get_dn(ld, e)), ldap_attr_gidnumber);
528 13
          free(dn);
529
          return NULL;
530
        }
531
532
        pw->pw_gid = ldap_defaultgid;
533
        ++i;
534 36
        pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": using default GID %lu", (unsigned long)pw->pw_gid);
535 13
        continue;
536
      }
537
538 20
      if (strcasecmp(ldap_attrs[i], ldap_attr_homedirectory) == 0) {
539
        if (!ldap_genhdir || !ldap_genhdir_prefix || !*ldap_genhdir_prefix) {
540 32
          pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): no %s attr for DN %s and LDAPGenerateHomedirPrefix was not enabled!", (dn = ldap_get_dn(ld, e)), ldap_attr_homedirectory);
541 13
          free(dn);
542
          return NULL;
543
        }
544
545 26
        if (ldap_genhdir_prefix_nouname) {
546 20
          pw->pw_dir = pstrcat(session.pool, ldap_genhdir_prefix, NULL);
547 26
        } else {
548 36
          LDAP_VALUE_T **canon_username;
549
          canon_username = LDAP_GET_VALUES(ld, e, ldap_attr_uid);
550
          if (!canon_username) {
551 32
            pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): couldn't get %s attr for canonical username for %s", ldap_attr_uid, (dn = ldap_get_dn(ld, e)));
552 18
            free(dn);
553
            return NULL;
554
          }
555
556 36
          pw->pw_dir = pstrcat(session.pool, ldap_genhdir_prefix, "/", LDAP_VALUE(canon_username, 0), NULL);
557
          LDAP_VALUE_FREE(canon_username);
558 18
        }
559 13
560
        ++i;
561 32
        pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": using default homedir %s", pw->pw_dir);
562 13
        continue;
563 4
      }
564
565 17
      /* Don't worry if we don't have a loginShell attr. */
566 20
      if (strcasecmp(ldap_attrs[i], ldap_attr_loginshell) == 0) {
567 13
        /* Prevent a segfault if no loginShell attr && RequireValidShell on. */
568 8
        pw->pw_shell = pstrdup(session.pool, "");
569 5
        ++i;
570
        continue;
571
      }
572
573 13
      /* We only restart the while loop above if we can fill in alternate
574 18
       * values for certain attributes. If something odd has happened, we
575
       * fall through to here and will complain about not being able to find
576
       * the attr.
577
       */
578 4
579 36
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): couldn't get values for attr %s for DN %s, ignoring request (perhaps this DN's entry does not have the attr?)", ldap_attrs[i], (dn = ldap_get_dn(ld, e)));
580 13
      free(dn);
581 17
      ldap_msgfree(result);
582 4
      return NULL;
583
    }
584
585 13
    /* Once we get here, we've already handled the "attribute defaults"
586 18
     * situation, so we can just fill in the struct as normal; the if
587
     * branches below for nonexistant attrs will just never be called.
588
     */
589 4
590 26
    if (strcasecmp(ldap_attrs[i], ldap_attr_uid) == 0) {
591 36
      pw->pw_name = pstrdup(session.pool, LDAP_VALUE(values, 0));
592 26
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_userpassword) == 0) {
593 36
      pw->pw_passwd = pstrdup(session.pool, LDAP_VALUE(values, 0));
594 26
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_uidnumber) == 0) {
595
      if (ldap_forcedefaultuid && ldap_defaultuid != -1) {
596 13
        pw->pw_uid = ldap_defaultuid;
597 26
      } else {
598 36
        pw->pw_uid = (uid_t) strtoul(LDAP_VALUE(values, 0), (char **)NULL, 10);
599 26
      }
600
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_gidnumber) == 0) {
601
      if (ldap_forcedefaultgid && ldap_defaultgid != -1) {
602 13
        pw->pw_gid = ldap_defaultgid;
603 26
      } else {
604 36
        pw->pw_gid = (gid_t) strtoul(LDAP_VALUE(values, 0), (char **)NULL, 10);
605 26
      }
606
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_homedirectory) == 0) {
607 20
      if (ldap_forcegenhdir) {
608
        if (!ldap_genhdir || !ldap_genhdir_prefix || !*ldap_genhdir_prefix) {
609 32
          pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): LDAPForceGeneratedHomedir is enabled, but LDAPGenerateHomedir is not.");
610 18
          return NULL;
611
        }
612
613 26
        if (ldap_genhdir_prefix_nouname) {
614 20
          pw->pw_dir = pstrcat(session.pool, ldap_genhdir_prefix, NULL);
615 26
        } else {
616 36
          LDAP_VALUE_T **canon_username;
617
          canon_username = LDAP_GET_VALUES(ld, e, ldap_attr_uid);
618
          if (!canon_username) {
619 32
            pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): couldn't get %s attr for canonical username for %s", ldap_attr_uid, (dn = ldap_get_dn(ld, e)));
620 18
            free(dn);
621
            return NULL;
622
          }
623
624 36
          pw->pw_dir = pstrcat(session.pool, ldap_genhdir_prefix, "/", LDAP_VALUE(canon_username, 0), NULL);
625
          LDAP_VALUE_FREE(canon_username);
626 18
        }
627 26
      } else {
628 36
        pw->pw_dir = pstrdup(session.pool, LDAP_VALUE(values, 0));
629 26
      }
630
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_loginshell) == 0) {
631 36
      pw->pw_shell = pstrdup(session.pool, LDAP_VALUE(values, 0));
632 26
    } else {
633 36
      pr_log_pri(PR_LOG_WARNING, MOD_LDAP_VERSION ": pr_ldap_user_lookup(): value loop found unknown attr %s", ldap_attrs[i]);
634
    }
635
636
    LDAP_VALUE_FREE(values);
637 4
    ++i;
638
  }
639
640 13
  /* If we're doing auth binds, save the DN of this entry so we can
641 18
   * bind to the LDAP server as it later.
642
   */
643 26
  if (user_dn) {
644 13
    *user_dn = ldap_get_dn(ld, e);
645 26
  }
646 13
647 4
  ldap_msgfree(result);
648 32
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": "
649
    "user %s, uid %lu, gid %lu, homedir %s, shell %s",
650 36
    pw->pw_name, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid,
651
    pw->pw_dir, pw->pw_shell);
652 4
  return pw;
653
}
654
655 17
static struct group *
656
pr_ldap_group_lookup(pool *p,
657
                     char *filter_template, const char *replace,
658
                     char *ldap_attrs[])
659 4
{
660 36
  char *filter, *dn;
661 84
  int i = 0, value_count, value_offset;
662 43
  struct group *gr;
663 4
  LDAPMessage *result, *e;
664 36
  LDAP_VALUE_T **values;
665 13
666 26
  if (!ldap_gid_basedn) {
667 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": no LDAP base DN specified for GID lookups");
668 13
    return NULL;
669
  }
670 4
671 72
  filter = pr_ldap_interpolate_filter(p, filter_template, replace);
672 73
  if (!filter) {
673
    return NULL;
674
  }
675 13
676 84
  result = pr_ldap_search(ldap_gid_basedn, filter, ldap_attrs, 2);
677
  if (result == NULL) {
678
    return NULL;
679 4
  }
680
681 36
  e = ldap_first_entry(ld, result);
682
  if (!e) {
683 4
    ldap_msgfree(result);
684 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no entries for filter %s", filter);
685 4
    return NULL; /* No LDAP entries for this user */
686
  }
687
688 43
  gr = pcalloc(session.pool, sizeof(struct group));
689 4
  while (ldap_attrs[i] != NULL) {
690 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": fetching value(s) for attr %s", ldap_attrs[i]);
691
692 36
    values = LDAP_GET_VALUES(ld, e, ldap_attrs[i]);
693
    if (!values) {
694 20
      if (strcasecmp(ldap_attrs[i], ldap_attr_memberuid) == 0) {
695 19
        gr->gr_mem = palloc(session.pool, 2 * sizeof(char *));
696 13
        gr->gr_mem[0] = pstrdup(session.pool, "");
697
        gr->gr_mem[1] = NULL;
698 8
699 13
        ++i;
700
        continue;
701 8
      }
702
703 4
      ldap_msgfree(result);
704 36
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_group_lookup(): couldn't get values for attr %s for DN %s, ignoring request (perhaps that DN does not have that attr?)", ldap_attrs[i], (dn = ldap_get_dn(ld, e)));
705 13
      free(dn);
706 4
      return NULL;
707
    }
708
709 26
    if (strcasecmp(ldap_attrs[i], ldap_attr_cn) == 0) {
710 36
      gr->gr_name = pstrdup(session.pool, LDAP_VALUE(values, 0));
711 26
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_gidnumber) == 0) {
712 36
      gr->gr_gid = strtoul(LDAP_VALUE(values, 0), (char **)NULL, 10);
713 26
    } else if (strcasecmp(ldap_attrs[i], ldap_attr_memberuid) == 0) {
714 36
      value_count = LDAP_COUNT_VALUES(values);
715 19
      gr->gr_mem = (char **) palloc(session.pool, value_count * sizeof(char *));
716 4
717 19
      for (value_offset = 0; value_offset < value_count; ++value_offset)
718 36
        gr->gr_mem[value_offset] =
719
          pstrdup(session.pool, LDAP_VALUE(values, value_offset));
720 26
    } else {
721 36
      pr_log_pri(PR_LOG_WARNING, MOD_LDAP_VERSION ": pr_ldap_group_lookup(): value loop found unknown attr %s", ldap_attrs[i]);
722
    }
723
724
    LDAP_VALUE_FREE(values);
725 4
    ++i;
726
  }
727
728
  ldap_msgfree(result);
729 32
  /* FIXME: member logging. */
730
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": "
731 36
    "group %s, gid %lu", gr->gr_name, (unsigned long)gr->gr_gid);
732 4
  return gr;
733
}
734
735 19
static void
736
parse_quota(pool *p, const char *replace, char *str)
737
{
738
  char **elts, *token;
739
740 26
  if (cached_quota == NULL) {
741 19
    cached_quota = make_array(p, 9, sizeof(char *));
742 26
  }
743 19
  elts = (char **)cached_quota->elts;
744
  elts[0] = pstrdup(session.pool, replace);
745
  cached_quota->nelts = 1;
746
747
  while ((token = strsep(&str, ","))) {
748
    *((char **)push_array(cached_quota)) = pstrdup(session.pool, token);
749
  }
750 32
  pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": parsed quota %s", str);
751 19
}
752
753 18
static unsigned char
754
pr_ldap_quota_lookup(pool *p, char *filter_template, const char *replace,
755
                     char *basedn)
756
{
757 36
  char *filter, *attrs[] = {ldap_attr_ftpquota, NULL};
758 18
  LDAPMessage *result, *e;
759 36
  LDAP_VALUE_T **values;
760 18
761 26
  if (!basedn) {
762 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": no LDAP base DN specified for auth/UID lookups, declining request.");
763 18
    return FALSE;
764
  }
765
766 72
  filter = pr_ldap_interpolate_filter(p, filter_template, replace);
767 73
  if (!filter) {
768
    return FALSE;
769
  }
770 18
771 84
  result = pr_ldap_search(basedn, filter, attrs, 2);
772
  if (result == NULL) {
773
    return FALSE;
774 18
  }
775
776
  if (ldap_count_entries(ld, result) > 1) {
777 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": pr_ldap_quota_lookup(): LDAP search returned multiple entries, aborting query");
778 18
    ldap_msgfree(result);
779 19
    if (ldap_default_quota != NULL) {
780
      parse_quota(p, replace, pstrdup(p, ldap_default_quota));
781
      return TRUE;
782
    }
783 18
    return FALSE;
784
  }
785
786 36
  e = ldap_first_entry(ld, result);
787
  if (!e) {
788 18
    ldap_msgfree(result);
789 19
    if (ldap_default_quota != NULL) {
790 32
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no entries for filter %s, using default quota %s", filter, ldap_default_quota);
791 19
      parse_quota(p, replace, pstrdup(p, ldap_default_quota));
792
      return TRUE;
793 32
    } else {
794
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no entries for filter %s, and no default quota defined", filter);
795 19
    }
796 18
    return FALSE; /* No LDAP entries for this user. */
797
  }
798
799 36
  values = LDAP_GET_VALUES(ld, e, attrs[0]);
800
  if (!values) {
801 18
    ldap_msgfree(result);
802 19
    if (ldap_default_quota != NULL) {
803 32
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no %s attribute, using default quota %s", attrs[0], ldap_default_quota);
804 19
      parse_quota(p, replace, pstrdup(p, ldap_default_quota));
805
      return TRUE;
806 32
    } else {
807
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no %s attribute, and no default quota defined", attrs[0]);
808 19
    }
809 18
    return FALSE; /* No quota attr for this user. */
810
  }
811
812 36
  parse_quota(p, replace, pstrdup(p, LDAP_VALUE(values, 0)));
813
  LDAP_VALUE_FREE(values);
814 18
  ldap_msgfree(result);
815
816
  return TRUE;
817
}
818
819 13
static struct group *
820 16
pr_ldap_getgrnam(pool *p, const char *group_name)
821 13
{
822 62
  char *group_attrs[] = {ldap_attr_cn, ldap_attr_gidnumber,
823
                         ldap_attr_memberuid, NULL};
824 13
825 26
  return pr_ldap_group_lookup(p, ldap_group_name_filter,
826
    group_name, group_attrs);
827 13
}
828
829
static struct group *
830 16
pr_ldap_getgrgid(pool *p, gid_t gid)
831 13
{
832 18
  char gidstr[PR_TUNABLE_BUFFER_SIZE] = {'\0'},
833 26
       *group_attrs[] = {ldap_attr_cn, ldap_attr_gidnumber,
834
                         ldap_attr_memberuid, NULL};
835 13
836 20
  snprintf(gidstr, sizeof(gidstr), "%u", (unsigned)gid);
837 13
838 26
  return pr_ldap_group_lookup(p, ldap_group_gid_filter,
839
    (const char *)gidstr, group_attrs);
840 13
}
841
842
static struct passwd *
843 16
pr_ldap_getpwnam(pool *p, const char *username)
844 13
{
845 73
  char *filter,
846
       *name_attrs[] = {ldap_attr_userpassword, ldap_attr_uid,
847 26
                        ldap_attr_uidnumber, ldap_attr_gidnumber,
848
                        ldap_attr_homedirectory, ldap_attr_loginshell, NULL};
849 13
850 73
  filter = pr_ldap_interpolate_filter(p, ldap_auth_basedn, username);
851
  if (!filter) {
852
    return NULL;
853
  }
854
855 13
  /* pr_ldap_user_lookup() returns NULL if it doesn't find an entry or
856 18
   * encounters an error. If everything goes all right, it returns a
857
   * struct passwd, so we can just return its result directly.
858
   *
859
   * We also do some cute stuff here to work around lameness in LDAP servers
860
   * like Sun Directory Services (SDS) 1.x and 3.x. If you request an attr
861
   * that you don't have access to, SDS totally ignores any entries with
862
   * that attribute. Thank you, Sun; how very smart of you. So if we're
863
   * doing auth binds, we don't request the userPassword attr.
864 20
   *
865
   * NOTE: if the UserPassword directive is configured, mod_auth will pass
866
   * a crypted password to handle_ldap_check(), which will NOT do auth binds
867
   * in order to support UserPassword. (Otherwise, it would try binding to
868
   * the directory and would ignore UserPassword.)
869
   *
870
   * We're reasonably safe in making that assumption as long as we never
871
   * fetch userPassword from the directory if auth binds are enabled. If we
872
   * fetched userPassword, auth binds would never be done because
873
   * handle_ldap_check() would always get a crypted password.
874 18
   */
875 73
  return pr_ldap_user_lookup(p, ldap_auth_filter, username, filter,
876 26
    ldap_authbinds ? name_attrs + 1 : name_attrs,
877
    ldap_authbinds ? &ldap_authbind_dn : NULL);
878 4
}
879
880 13
static struct passwd *
881 16
pr_ldap_getpwuid(pool *p, uid_t uid)
882 8
{
883 18
  char uidstr[PR_TUNABLE_BUFFER_SIZE] = {'\0'},
884 20
       *uid_attrs[] = {ldap_attr_uid, ldap_attr_uidnumber, ldap_attr_gidnumber,
885
                       ldap_attr_homedirectory, ldap_attr_loginshell, NULL};
886 4
887 20
  snprintf(uidstr, sizeof(uidstr), "%u", (unsigned)uid);
888 10
889 13
  /* pr_ldap_user_lookup() returns NULL if it doesn't find an entry or
890 18
   * encounters an error. If everything goes all right, it returns a
891
   * struct passwd, so we can just return its result directly.
892
   */
893
  return pr_ldap_user_lookup(p, ldap_uid_filter, (const char *)uidstr,
894 26
    ldap_uid_basedn, uid_attrs, ldap_authbinds ? &ldap_authbind_dn : NULL);
895 13
}
896
897
MODRET
898 18
handle_ldap_quota_lookup(cmd_rec *cmd)
899
{
900
  if (cached_quota == NULL ||
901 26
      strcasecmp(((char **)cached_quota->elts)[0], cmd->argv[0]) != 0)
902 18
  {
903
    if (pr_ldap_quota_lookup(cmd->tmp_pool, ldap_quota_filter,
904
                             cmd->argv[0], ldap_quota_basedn) == FALSE)
905
    {
906 28
      return PR_DECLINED(cmd);
907 18
    }
908 32
  } else {
909
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": returning cached quota for %s", cmd->argv[0]);
910 18
  }
911
912
  return mod_create_data(cmd, cached_quota);
913
}
914
915
MODRET
916 13
handle_ldap_setpwent(cmd_rec *cmd)
917
{
918
  if (ldap_doauth || ldap_douid || ldap_dogid) {
919 26
    if (!ld) {
920 20
      (void) pr_ldap_connect(&ld, TRUE);
921 26
    }
922 28
    return PR_HANDLED(cmd);
923
  }
924
925
  return PR_DECLINED(cmd);
926 13
}
927
928
MODRET
929
handle_ldap_endpwent(cmd_rec *cmd)
930
{
931
  if (ldap_doauth || ldap_douid || ldap_dogid) {
932
    pr_ldap_unbind();
933 28
    return PR_HANDLED(cmd);
934
  }
935
936
  return PR_DECLINED(cmd);
937 13
}
938
939
MODRET
940
handle_ldap_getpwuid(cmd_rec *cmd)
941
{
942 43
  struct passwd *pw;
943
944 26
  if (!ldap_douid) {
945 28
    return PR_DECLINED(cmd);
946 26
  }
947
948 43
  pw = pr_ldap_getpwuid(cmd->tmp_pool, *((uid_t *) cmd->argv[0]));
949 36
  if (pw) {
950 13
    return mod_create_data(cmd, pw);
951 26
  }
952 13
953 28
  return PR_DECLINED(cmd);
954 4
}
955
956 13
MODRET
957
handle_ldap_getpwnam(cmd_rec *cmd)
958 4
{
959 43
  struct passwd *pw;
960
961 26
  if (!ldap_doauth) {
962 28
    return PR_DECLINED(cmd);
963 26
  }
964
965 36
  pw = pr_ldap_getpwnam(cmd->tmp_pool, cmd->argv[0]);
966
  if (pw) {
967 13
    return mod_create_data(cmd, pw);
968 26
  }
969 13
970 28
  return PR_DECLINED(cmd);
971 13
}
972
973
MODRET
974
handle_ldap_getgrnam(cmd_rec *cmd)
975
{
976 43
  struct group *gr;
977
978 26
  if (!ldap_dogid) {
979 28
    return PR_DECLINED(cmd);
980 26
  }
981
982 36
  gr = pr_ldap_getgrnam(cmd->tmp_pool, cmd->argv[0]);
983
  if (gr) {
984 13
    return mod_create_data(cmd, gr);
985 26
  }
986 13
987 28
  return PR_DECLINED(cmd);
988 13
}
989
990
MODRET
991
handle_ldap_getgrgid(cmd_rec *cmd)
992
{
993 43
  struct group *gr;
994
995 26
  if (!ldap_dogid) {
996 28
    return PR_DECLINED(cmd);
997 26
  }
998
999 43
  gr = pr_ldap_getgrgid(cmd->tmp_pool, *((gid_t *) cmd->argv[0]));
1000
  if (!gr) {
1001
    return PR_DECLINED(cmd);
1002 26
  }
1003 13
1004 43
  return mod_create_data(cmd, gr);
1005 13
}
1006
1007 16
MODRET
1008
handle_ldap_getgroups(cmd_rec *cmd)
1009
{
1010 36
  char *filter, *w[] = {ldap_attr_gidnumber, ldap_attr_cn, NULL};
1011 16
  int ret;
1012
  struct passwd *pw;
1013
  struct group *gr;
1014
  LDAPMessage *result = NULL, *e;
1015 36
  LDAP_VALUE_T **gidNumber, **cn;
1016 16
  array_header *gids   = (array_header *)cmd->argv[1],
1017
               *groups = (array_header *)cmd->argv[2];
1018
1019 26
  if (!ldap_dogid) {
1020 28
    return PR_DECLINED(cmd);
1021 26
  }
1022
1023
  if (!gids || !groups) {
1024 28
    return PR_DECLINED(cmd);
1025 26
  }
1026 16
1027 36
  pw = pr_ldap_getpwnam(cmd->tmp_pool, cmd->argv[0]);
1028
  if (pw) {
1029
    gr = pr_ldap_getgrgid(cmd->tmp_pool, pw->pw_gid);
1030
    if (gr) {
1031
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": adding user %s primary group %s/%lu", pw->pw_name, gr->gr_name, (unsigned long)pw->pw_gid);
1032 16
      *((gid_t *) push_array(gids))   = pw->pw_gid;
1033
      *((char **) push_array(groups)) = pstrdup(session.pool, gr->gr_name);
1034 32
    } else {
1035 36
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": couldn't determine group name for user %s primary group %lu, skipping.", pw->pw_name, (unsigned long)pw->pw_gid);
1036 16
    }
1037
  }
1038
1039 26
  if (!ldap_gid_basedn) {
1040 32
    pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": no LDAP base DN specified for GID lookups");
1041 16
    goto return_groups;
1042
  }
1043
1044 73
  filter = pr_ldap_interpolate_filter(cmd->tmp_pool,
1045
    ldap_group_member_filter, cmd->argv[0]);
1046
  if (!filter) {
1047
    return NULL;
1048
  }
1049 16
1050 84
  result = pr_ldap_search(ldap_gid_basedn, filter, w, 0);
1051
  if (result == NULL) {
1052
    return FALSE;
1053 16
  }
1054
1055 26
  if (ldap_count_entries(ld, result) == 0) {
1056 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": no entries for filter %s", filter);
1057 16
    goto return_groups;
1058 26
  }
1059 16
1060
  for (e = ldap_first_entry(ld, result); e; e = ldap_next_entry(ld, e)) {
1061 36
    gidNumber = LDAP_GET_VALUES(ld, e, w[0]);
1062
    if (!gidNumber) {
1063
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": ldap_handle_getgroups(): couldn't get values for %s attr, skipping current group: %s", ldap_err2string(ret), ldap_attr_gidnumber);
1064 16
      continue;
1065
    }
1066 36
    cn = LDAP_GET_VALUES(ld, e, w[1]);
1067
    if (!cn) {
1068
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": ldap_handle_getgroups(): couldn't get values for %s attr, skipping current group: %s", ldap_err2string(ret), ldap_attr_cn);
1069 16
      continue;
1070
    }
1071
1072 36
    if (!pw || strtoul(LDAP_VALUE(gidNumber, 0), (char **)NULL, 10) != pw->pw_gid) {
1073
      *((gid_t *) push_array(gids)) =
1074
        strtoul(LDAP_VALUE(gidNumber, 0), (char **)NULL, 10);
1075
      *((char **) push_array(groups)) = pstrdup(session.pool, LDAP_VALUE(cn, 0));
1076
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": added user %s secondary group %s/%s", pw->pw_name, LDAP_VALUE(cn, 0), LDAP_VALUE(gidNumber, 0));
1077
    }
1078
1079
    LDAP_VALUE_FREE(gidNumber);
1080
    LDAP_VALUE_FREE(cn);
1081 16
  }
1082
1083
return_groups:
1084 26
  if (result) {
1085 16
    ldap_msgfree(result);
1086 26
  }
1087
1088
  if (gids->nelts > 0) {
1089 20
    return mod_create_data(cmd, (void *) &gids->nelts);
1090 26
  }
1091 28
  return PR_DECLINED(cmd);
1092 16
}
1093
1094 13
1095
/****************************
1096
 * High-level auth handlers *
1097
 ****************************/
1098 4
1099
/* cmd->argv[0] : user name
1100
 * cmd->argv[1] : cleartext password
1101
 */
1102
1103 13
MODRET
1104
handle_ldap_is_auth(cmd_rec *cmd)
1105 4
{
1106 13
  const char *username = cmd->argv[0];
1107 73
  char *filter,
1108
       *pass_attrs[] = {ldap_attr_userpassword, ldap_attr_uid,
1109 62
                        ldap_attr_uidnumber, ldap_attr_gidnumber,
1110
                        ldap_attr_homedirectory, ldap_attr_loginshell, NULL};
1111 43
  struct passwd *pw;
1112 4
1113 26
  if (!ldap_doauth) {
1114 28
    return PR_DECLINED(cmd);
1115 26
  }
1116 4
1117 73
  filter = pr_ldap_interpolate_filter(cmd->tmp_pool,
1118
    ldap_auth_basedn, username);
1119
  if (!filter) {
1120
    return NULL;
1121
  }
1122
1123 13
  /* If anything here fails hard (IOW, we've found an LDAP entry for the
1124
   * user, but they appear to have entered the wrong password), boot them.
1125
   * Normally, I'd DECLINE here so other modules could have a shot, but if
1126
   * we've found their LDAP entry, chances are that nothing else is going to
1127
   * be able to auth them. If anyone has a reason that this shouldn't be
1128
   * this way, then by all means, let me know.
1129
   */
1130
1131 73
  pw = pr_ldap_user_lookup(cmd->tmp_pool,
1132
    ldap_auth_filter, username, filter,
1133 43
    ldap_authbinds ? pass_attrs + 1 : pass_attrs,
1134
    ldap_authbinds ? &ldap_authbind_dn : NULL);
1135
  if (!pw) {
1136
    return PR_DECLINED(cmd); /* Can't find the user in the LDAP directory. */
1137 32
  }
1138 26
1139
  if (!ldap_authbinds && !pw->pw_passwd) {
1140 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": LDAPAuthBinds is not enabled, and couldn't fetch a password for %s", pw->pw_name);
1141 28
    return PR_ERROR_INT(cmd, PR_AUTH_NOPWD);
1142 26
  }
1143 5
1144 86
  if (pr_auth_check(cmd->tmp_pool, ldap_authbinds ? NULL : pw->pw_passwd,
1145 32
                    username, cmd->argv[1]))
1146 18
  {
1147 32
    pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": bad password for %s", pw->pw_name);
1148 28
    return PR_ERROR_INT(cmd, PR_AUTH_BADPWD);
1149 18
  }
1150 4
1151 23
  session.auth_mech = "mod_ldap.c";
1152 28
  return PR_HANDLED(cmd);
1153 4
}
1154
1155 13
/* cmd->argv[0] = hashed password,
1156 4
 * cmd->argv[1] = user,
1157
 * cmd->argv[2] = cleartext
1158
 */
1159
1160 13
MODRET
1161
handle_ldap_check(cmd_rec *cmd)
1162 4
{
1163 13
  char *pass, *cryptpass, *hash_method;
1164 20
  int encname_len, ret;
1165 13
  LDAP *ld_auth;
1166 85
#ifdef HAS_LDAP_SASL_BIND_S
1167 36
  struct berval bindcred;
1168
#endif
1169 4
1170 31
#if defined(HAVE_OPENSSL) || defined(PR_USE_OPENSSL)
1171 8
  EVP_MD_CTX EVP_Context;
1172
  const EVP_MD *md;
1173 61
  unsigned int md_len;
1174 8
  unsigned char md_value[EVP_MAX_MD_SIZE];
1175
  EVP_ENCODE_CTX EVP_Encode;
1176 61
1177
  /* According to RATS, the output buffer (buff) for EVP_EncodeBlock() needs
1178
   * to be 4/3 the size of the input buffer (md_val).  Let's make it easy, and
1179
   * use an output buffer that's twice the size of the input buffer.
1180
   */
1181
  unsigned char buff[EVP_MAX_MD_SIZE * 2];
1182
1183 31
#endif /* !HAVE_OPENSSL and !PR_USE_OPENSSL */
1184 8
1185 26
  if (!ldap_doauth) {
1186 28
    return PR_DECLINED(cmd);
1187 26
  }
1188 4
1189 13
  cryptpass = cmd->argv[0];
1190 86
  pass = cmd->argv[2];
1191
1192
1193
  /* At this point, any encrypted password must have come from
1194
   * the UserPassword directive. Don't perform auth binds in this
1195
   * case, since the crypted password specified should override
1196
   * auth binds.
1197
   */
1198
  if (ldap_authbinds && cryptpass == NULL) {
1199
    /* Don't try to do auth binds with a NULL/empty DN or password. */
1200
    if ((pass == NULL) || (strlen(pass) == 0)) {
1201
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": check: LDAPAuthBinds is enabled, but no user-supplied cleartext password was provided.");
1202 28
      return PR_DECLINED(cmd);
1203 20
    }
1204 86
    if ((ldap_authbind_dn == NULL) || (strlen(ldap_authbind_dn) == 0)) {
1205
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": check: LDAPAuthBinds is enabled, but no LDAP DN was found.");
1206 28
      return PR_DECLINED(cmd);
1207 20
    }
1208
1209
    if (pr_ldap_connect(&ld_auth, FALSE) == -1) {
1210 86
      pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": handle_ldap_check(): pr_ldap_connect() failed.");
1211 28
      return PR_DECLINED(cmd);
1212 20
    }
1213
1214 85
#ifdef HAS_LDAP_SASL_BIND_S
1215 36
    bindcred.bv_val = cmd->argv[2];
1216
    bindcred.bv_len = strlen(cmd->argv[2]);
1217
    ret = ldap_sasl_bind_s(ld_auth, ldap_authbind_dn, NULL, &bindcred,
1218
      NULL, NULL, NULL);
1219 85
#else /* HAS_LDAP_SASL_BIND_S */
1220 36
    ret = ldap_simple_bind_s(ld_auth, ldap_authbind_dn, cmd->argv[2]);
1221 85
#endif /* HAS_LDAP_SASL_BIND_S */
1222 36
1223
    if (ret != LDAP_SUCCESS) {
1224 26
      if (ret != LDAP_INVALID_CREDENTIALS) {
1225 36
        pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": handle_ldap_check(): bind as %s failed: %s", ldap_authbind_dn, ldap_err2string(ret));
1226 32
      }
1227
      pr_log_debug(DEBUG3, MOD_LDAP_VERSION ": invalid credentials for %s", ldap_authbind_dn);
1228 36
      LDAP_UNBIND(ld_auth);
1229 28
      return PR_ERROR(cmd);
1230 13
    }
1231
1232 36
    LDAP_UNBIND(ld_auth);
1233 23
    session.auth_mech = "mod_ldap.c";
1234 28
    return PR_HANDLED(cmd);
1235 5
  }
1236
1237 4
  /* Get the length of "scheme" in the leading {scheme} so we can skip it
1238 18
   * in the password comparison.
1239
   */
1240 13
  encname_len = strcspn(cryptpass + 1, "}");
1241
  hash_method = pstrndup(cmd->tmp_pool, cryptpass + 1, encname_len);
1242 4
1243
  /* Check to see how the password is encrypted, and check accordingly. */
1244
1245 13
  if (encname_len == strlen(cryptpass + 1)) { /* No leading {scheme} */
1246 8
    if (ldap_defaultauthscheme && (strcasecmp(ldap_defaultauthscheme, "clear") == 0)) {
1247 26
      if (strcmp(pass, cryptpass) != 0) {
1248 28
        return PR_ERROR(cmd);
1249 26
      }
1250
    } else { /* else, assume crypt */
1251
      if (strcmp(crypt(pass, cryptpass), cryptpass) != 0) {
1252 28
        return PR_ERROR(cmd);
1253 26
      }
1254
    }
1255
  } else if (strncasecmp(hash_method, "crypt", strlen(hash_method)) == 0) { /* {crypt} */
1256
    if (strcmp(crypt(pass, cryptpass + encname_len + 2), cryptpass + encname_len + 2) != 0) {
1257 28
      return PR_ERROR(cmd);
1258 26
    }
1259
  } else if (strncasecmp(hash_method, "clear", strlen(hash_method)) == 0) { /* {clear} */
1260
    if (strcmp(pass, cryptpass + encname_len + 2) != 0) {
1261 28
      return PR_ERROR(cmd);
1262 26
    }
1263 4
  }
1264 31
#if defined(HAVE_OPENSSL) || defined(PR_USE_OPENSSL)
1265 8
  else { /* Try the cipher mode found */
1266 32
    pr_log_debug(DEBUG5, MOD_LDAP_VERSION ": %s-encrypted password found, trying to auth.", hash_method);
1267 8
1268
    SSLeay_add_all_digests();
1269
1270
    /* This is a kludge. This is only a kludge. OpenLDAP likes {sha}
1271 18
     * (at least, the OpenLDAP ldappasswd generates {sha}), but OpenSSL
1272
     * likes {sha1} and does not understand {sha}. We translate
1273
     * RMD160 -> RIPEMD160 here, too.
1274
     */
1275 26
    if (strncasecmp(hash_method, "SHA", 4) == 0) {
1276 8
        md = EVP_get_digestbyname("SHA1");
1277 26
    } else if (strncasecmp(hash_method, "RMD160", 7) == 0) {
1278 8
        md = EVP_get_digestbyname("RIPEMD160");
1279 26
    } else {
1280 8
        md = EVP_get_digestbyname(hash_method);
1281 26
    }
1282
1283
    if (!md) {
1284 32
      pr_log_debug(DEBUG5, MOD_LDAP_VERSION ": %s not supported by OpenSSL, declining auth request", hash_method);
1285 28
      return PR_DECLINED(cmd); /* Some other module may support it. */
1286 8
    }
1287
1288
    /* Make a digest of the user-supplied password. */
1289
    EVP_DigestInit(&EVP_Context, md);
1290 13
    EVP_DigestUpdate(&EVP_Context, pass, strlen(pass));
1291 8
    EVP_DigestFinal(&EVP_Context, md_value, &md_len);
1292
1293
    /* Base64 Encoding */
1294 61
    memset(buff, '\0', sizeof(buff));
1295 8
    EVP_EncodeInit(&EVP_Encode);
1296 61
    EVP_EncodeBlock(buff, md_value, (int) md_len);
1297 8
1298 61
    if (strcmp((char *) buff, cryptpass + encname_len + 2) != 0) {
1299 28
      return PR_ERROR(cmd);
1300 26
    }
1301 8
  }
1302 31
#else
1303 26
  else { /* Can't find a supported {scheme} */
1304 28
    return PR_DECLINED(cmd);
1305 26
  }
1306 31
#endif /* !HAVE_OPENSSL and !PR_USE_OPENSSL */
1307 4
1308 23
  session.auth_mech = "mod_ldap.c";
1309 28
  return PR_HANDLED(cmd);
1310 4
}
1311
1312 13
MODRET
1313
handle_ldap_uid_name(cmd_rec *cmd)
1314 4
{
1315 43
  struct passwd *pw;
1316 4
1317 26
  if (!ldap_douid) {
1318 28
    return PR_DECLINED(cmd);
1319 26
  }
1320 4
1321 43
  pw = pr_ldap_getpwuid(cmd->tmp_pool, *((uid_t *) cmd->argv[0]));
1322
  if (!pw) {
1323
    /* Can't find the user in the LDAP directory. */
1324
    return PR_DECLINED(cmd);
1325 4
  }
1326
1327 43
  return mod_create_data(cmd, pstrdup(permanent_pool, pw->pw_name));
1328 4
}
1329
1330 13
MODRET
1331
handle_ldap_gid_name(cmd_rec *cmd)
1332 4
{
1333 43
  struct group *gr;
1334 4
1335 26
  if (!ldap_dogid) {
1336 28
    return PR_DECLINED(cmd);
1337 26
  }
1338 4
1339 43
  gr = pr_ldap_getgrgid(cmd->tmp_pool, *((gid_t *) cmd->argv[0]));
1340
  if (!gr) {
1341
    /* Can't find the user in the LDAP directory. */
1342
    return PR_DECLINED(cmd);
1343 4
  }
1344
1345 43
  return mod_create_data(cmd, pstrdup(permanent_pool, gr->gr_name));
1346 4
}
1347
1348 13
MODRET
1349
handle_ldap_name_uid(cmd_rec *cmd)
1350 4
{
1351 43
  struct passwd *pw;
1352
1353 26
  if (!ldap_doauth) {
1354 28
    return PR_DECLINED(cmd);
1355 26
  }
1356
1357 36
  pw = pr_ldap_getpwnam(cmd->tmp_pool, cmd->argv[0]);
1358 43
  if (!pw) {
1359
    return PR_DECLINED(cmd);
1360 26
  }
1361 13
1362 43
  return mod_create_data(cmd, (void *) &pw->pw_uid);
1363 4
}
1364
1365 13
MODRET
1366
handle_ldap_name_gid(cmd_rec *cmd)
1367 4
{
1368 43
  struct group *gr;
1369
1370 26
  if (!ldap_dogid) {
1371 28
    return PR_DECLINED(cmd);
1372 26
  }
1373
1374 36
  gr = pr_ldap_getgrnam(cmd->tmp_pool, cmd->argv[0]);
1375 43
  if (!gr) {
1376
    return PR_DECLINED(cmd);
1377 26
  }
1378 13
1379 43
  return mod_create_data(cmd, (void *) &gr->gr_gid);
1380 4
}
1381
1382 13
1383
/*****************************************
1384
 * Config-file handlers/parsing routines *
1385
 *****************************************/
1386
1387
MODRET
1388
set_ldap_server(cmd_rec *cmd)
1389 4
{
1390 77
  int i, len;
1391
  char *item;
1392 38
  LDAPURLDesc *url;
1393 77
  array_header *urls = NULL;
1394
  config_rec *c;
1395 38
1396 13
  CHECK_ARGS(cmd, 1);
1397
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1398 4
1399 77
  c = add_config_param(cmd->argv[0], 1, NULL);
1400
  urls = make_array(c->pool, cmd->argc - 1, sizeof(char *));
1401
  c->argv[0] = urls;
1402
1403
  for (i = 1; i < cmd->argc; ++i) {
1404
    if (ldap_is_ldap_url(cmd->argv[i])) {
1405
      if (ldap_url_parse(cmd->argv[i], &url) != LDAP_URL_SUCCESS) {
1406
        CONF_ERROR(cmd, "LDAPServer: must be supplied with a valid LDAP URL.");
1407
      }
1408
1409
      if (find_config(main_server->conf, CONF_PARAM, "LDAPSearchScope", FALSE)) {
1410
        CONF_ERROR(cmd, "LDAPSearchScope cannot be used when LDAPServer specifies a URL; specify a search scope in the LDAPServer URL instead.");
1411
      }
1412 57
1413 85
#ifdef HAS_LDAP_INITIALIZE
1414 77
      if (strncasecmp(cmd->argv[i], "ldap:", strlen("ldap:")) != 0 &&
1415
          strncasecmp(cmd->argv[i], "ldaps:", strlen("ldaps:")) != 0) {
1416 38
1417 77
        CONF_ERROR(cmd, "Invalid scheme specified by LDAPServer URL. Valid schemes are 'ldap' or 'ldaps'.");
1418
      }
1419 85
#else /* HAS_LDAP_INITIALIZE */
1420 77
      if (strncasecmp(cmd->argv[i], "ldap:", strlen("ldap:")) != 0) {
1421
        CONF_ERROR(cmd, "Invalid scheme specified by LDAPServer URL. Valid schemes are 'ldap'.");
1422
      }
1423 85
#endif /* HAS_LDAP_INITIALIZE */
1424 37
1425 77
      if (url->lud_dn && strcmp(url->lud_dn, "") != 0) {
1426
        CONF_ERROR(cmd, "A base DN may not be specified by an LDAPServer URL, only by LDAPDoAuth, LDAPDoUIDLookups, LDAPDoGIDLookups, or LDAPDoQuotaLookups.");
1427
      }
1428
      if (url->lud_filter && strcmp(url->lud_filter, "") != 0) {
1429
        CONF_ERROR(cmd, "A search filter may not be specified by an LDAPServer URL, only by LDAPDoAuth, LDAPDoUIDLookups, LDAPDoGIDLookups, or LDAPDoQuotaLookups.");
1430
      }
1431
1432
      ldap_free_urldesc(url);
1433
      *((char **)push_array(urls)) = pstrdup(c->pool, cmd->argv[i]);
1434
    } else {
1435
      /* Split non-URL arguments on whitespace and insert them as
1436
       * separate servers.
1437
       */
1438
      item = cmd->argv[i];
1439
      while (*item) {
1440
        len = strcspn(item, " \f\n\r\t\v");
1441
        *((char **)push_array(urls)) = pstrndup(c->pool, item, len);
1442
1443
        item += len;
1444
        while (isspace(*item)) {
1445
          ++item;
1446
        }
1447
      }
1448
    }
1449 38
  }
1450
1451 28
  return PR_HANDLED(cmd);
1452 4
}
1453
1454 13
MODRET
1455
set_ldap_dninfo(cmd_rec *cmd)
1456 4
{
1457 13
  CHECK_ARGS(cmd, 1);
1458
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1459 4
1460 24
  add_config_param_str(cmd->argv[0], 2, cmd->argv[1], cmd->argv[2]);
1461 28
  return PR_HANDLED(cmd);
1462 4
}
1463
1464 13
MODRET
1465
set_ldap_authbinds(cmd_rec *cmd)
1466 5
{
1467
  int b;
1468 24
  config_rec *c;
1469 5
1470 13
  CHECK_ARGS(cmd, 1);
1471
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1472 5
1473 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1474 13
    CONF_ERROR(cmd, "LDAPAuthBinds: expected a boolean value for first argument.");
1475 26
  }
1476 5
1477 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1478
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1479
  *((int *) c->argv[0]) = b;
1480
1481 28
  return PR_HANDLED(cmd);
1482 5
}
1483
1484 13
MODRET
1485
set_ldap_querytimeout(cmd_rec *cmd)
1486 4
{
1487 24
  config_rec *c;
1488
  int timeout;
1489
1490 13
  CHECK_ARGS(cmd, 1);
1491
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1492 4
1493 24
  timeout = atoi(cmd->argv[1]);
1494
  if (timeout <= 0) {
1495
    CONF_ERROR(cmd, "LDAPQueryTimeout: timeout must be greater than zero.");
1496
  }
1497
1498
  c = add_config_param(cmd->argv[0], 1, NULL);
1499
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1500
  *((int *) c->argv[0]) = timeout;
1501
1502 28
  return PR_HANDLED(cmd);
1503 4
}
1504
1505 13
MODRET
1506
set_ldap_searchscope(cmd_rec *cmd)
1507 8
{
1508 57
  config_rec *c;
1509
1510 8
  CHECK_ARGS(cmd, 1);
1511
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1512
1513 57
  c = find_config(main_server->conf, CONF_PARAM, "LDAPServer", FALSE);
1514
  if (c && ldap_is_ldap_url(c->argv[0])) {
1515
    CONF_ERROR(cmd, "LDAPSearchScope cannot be used when LDAPServer specifies a URL; specify a search scope in the LDAPServer URL instead.");
1516
  }
1517
1518 24
  add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1519 28
  return PR_HANDLED(cmd);
1520 13
}
1521
1522
MODRET
1523 23
set_ldap_dereference(cmd_rec *cmd)
1524
{
1525
  int value;
1526 24
  config_rec *c;
1527
1528 23
  CHECK_ARGS(cmd, 1);
1529
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1530
1531
  if (strcasecmp(cmd->argv[1], "never") == 0) {
1532
    value = LDAP_DEREF_NEVER;
1533
  } else if (strcasecmp(cmd->argv[1], "search") == 0) {
1534
    value = LDAP_DEREF_SEARCHING;
1535
  } else if (strcasecmp(cmd->argv[1], "find") == 0) {
1536
    value = LDAP_DEREF_FINDING;
1537
  } else if (strcasecmp(cmd->argv[1], "always") == 0) {
1538
    value = LDAP_DEREF_ALWAYS;
1539
  } else {
1540
    CONF_ERROR(cmd, "LDAPAliasDereference: expected a valid dereference (never, search, find, always).");
1541
  }
1542
1543 24
  c = add_config_param("LDAPAliasDereference", 1, NULL);
1544
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1545
  *((int *) c->argv[0]) = value;
1546 28
  return PR_HANDLED(cmd);
1547 23
}
1548
1549
MODRET
1550 13
set_ldap_doauth(cmd_rec *cmd)
1551
{
1552
  int b;
1553
  config_rec *c;
1554
1555
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1556
1557 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1558 13
    CONF_ERROR(cmd, "LDAPDoAuth: expected a boolean value for first argument.");
1559 26
  }
1560 13
1561
  if (b == 1) { CHECK_ARGS(cmd, 2); }
1562
  else        { CHECK_ARGS(cmd, 1); }
1563
1564 25
  c = add_config_param(cmd->argv[0], cmd->argc - 1, NULL, NULL, NULL);
1565 24
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1566
  *((int *) c->argv[0]) = b;
1567 26
  if (cmd->argc > 2) {
1568 25
    c->argv[1] = pstrdup(c->pool, cmd->argv[2]);
1569 26
  }
1570
  if (cmd->argc > 3) {
1571 25
    c->argv[2] = pstrdup(c->pool, cmd->argv[3]);
1572 26
  }
1573 13
1574 28
  return PR_HANDLED(cmd);
1575 13
}
1576
1577
MODRET
1578
set_ldap_douid(cmd_rec *cmd)
1579
{
1580
  int b;
1581
  config_rec *c;
1582
1583
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1584
1585 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1586 13
    CONF_ERROR(cmd, "LDAPDoUIDLookups: expected a boolean value for first argument.");
1587 26
  }
1588 13
1589
  if (b == 1) { CHECK_ARGS(cmd, 2); }
1590
  else        { CHECK_ARGS(cmd, 1); }
1591
1592 25
  c = add_config_param(cmd->argv[0], cmd->argc - 1, NULL, NULL, NULL);
1593 24
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1594
  *((int *) c->argv[0]) = b;
1595 26
  if (cmd->argc > 2) {
1596 25
    c->argv[1] = pstrdup(c->pool, cmd->argv[2]);
1597 26
  }
1598
  if (cmd->argc > 3) {
1599 25
    c->argv[2] = pstrdup(c->pool, cmd->argv[3]);
1600 26
  }
1601 13
1602 28
  return PR_HANDLED(cmd);
1603 13
}
1604
1605
MODRET
1606
set_ldap_dogid(cmd_rec *cmd)
1607
{
1608
  int b;
1609
  config_rec *c;
1610
1611
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1612
1613 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1614 13
    CONF_ERROR(cmd, "LDAPDoGIDLookups: expected a boolean value for first argument.");
1615 26
  }
1616 13
1617
  if (b == 1) { CHECK_ARGS(cmd, 2); }
1618
  else        { CHECK_ARGS(cmd, 1); }
1619
1620 24
  c = add_config_param(cmd->argv[0], cmd->argc - 1, NULL);
1621
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1622
  *((int *) c->argv[0]) = b;
1623 26
  if (cmd->argc > 2) {
1624 17
    c->argv[1] = pstrdup(c->pool, cmd->argv[2]);
1625 26
  }
1626
  if (cmd->argc > 3) {
1627 17
    c->argv[2] = pstrdup(c->pool, cmd->argv[3]);
1628 26
  }
1629
  if (cmd->argc > 4) {
1630 17
    c->argv[3] = pstrdup(c->pool, cmd->argv[4]);
1631 26
  }
1632
  if (cmd->argc > 5) {
1633 17
    c->argv[4] = pstrdup(c->pool, cmd->argv[5]);
1634 26
  }
1635 13
1636 28
  return PR_HANDLED(cmd);
1637 13
}
1638
1639
MODRET
1640 18
set_ldap_doquota(cmd_rec *cmd)
1641
{
1642
  int b;
1643
  config_rec *c;
1644
1645
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1646
1647 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1648 18
    CONF_ERROR(cmd, "LDAPDoQuotaLookups: expected a boolean value for first argument.");
1649 26
  }
1650 18
1651
  if (b == 1) { CHECK_ARGS(cmd, 2); }
1652
  else        { CHECK_ARGS(cmd, 1); }
1653
1654 24
  c = add_config_param(cmd->argv[0], cmd->argc - 1, NULL);
1655
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1656
  *((int *) c->argv[0]) = b;
1657 26
  if (cmd->argc > 2) {
1658 18
    c->argv[1] = pstrdup(c->pool, cmd->argv[2]);
1659 26
  }
1660
  if (cmd->argc > 3) {
1661 18
    c->argv[2] = pstrdup(c->pool, cmd->argv[3]);
1662 26
  }
1663
  if (cmd->argc > 4) {
1664 19
    c->argv[3] = pstrdup(c->pool, cmd->argv[4]);
1665 26
  }
1666 18
1667 28
  return PR_HANDLED(cmd);
1668 18
}
1669
1670
MODRET
1671 13
set_ldap_defaultuid(cmd_rec *cmd)
1672
{
1673 25
  char *endptr;
1674 24
  config_rec *c;
1675 16
1676 13
  CHECK_ARGS(cmd, 1);
1677
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1678 16
1679 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1680
  c->argv[0] = pcalloc(c->pool, sizeof(uid_t));
1681 25
  *((uid_t *) c->argv[0]) = strtoul(cmd->argv[1], &endptr, 10);
1682 26
  if (*endptr != '\0') {
1683
    CONF_ERROR(cmd, "LDAPDefaultUID: UID argument must be numeric!");
1684
  }
1685 28
  return PR_HANDLED(cmd);
1686 4
}
1687
1688 13
MODRET
1689
set_ldap_defaultgid(cmd_rec *cmd)
1690 4
{
1691 25
  char *endptr;
1692 24
  config_rec *c;
1693 16
1694 13
  CHECK_ARGS(cmd, 1);
1695
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1696 16
1697 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1698
  c->argv[0] = pcalloc(c->pool, sizeof(gid_t));
1699 25
  *((gid_t *) c->argv[0]) = strtoul(cmd->argv[1], &endptr, 10);
1700 26
  if (*endptr != '\0') {
1701
    CONF_ERROR(cmd, "LDAPDefaultGID: GID argument must be numeric.");
1702
  }
1703 28
  return PR_HANDLED(cmd);
1704 4
}
1705
1706 13
MODRET set_ldap_forcedefaultuid(cmd_rec *cmd)
1707
{
1708
  int b;
1709 24
  config_rec *c;
1710 13
1711
  CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1712
1713 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1714 13
    CONF_ERROR(cmd, "LDAPForceDefaultUID: expected boolean argument for first argument.");
1715 26
  }
1716 13
1717 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1718
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1719
  *((int *) c->argv[0]) = b;
1720 28
  return PR_HANDLED(cmd);
1721 13
}
1722
1723
MODRET set_ldap_forcedefaultgid(cmd_rec *cmd)
1724
{
1725
  int b;
1726 24
  config_rec *c;
1727 13
1728
  CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1729
1730 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1731 13
    CONF_ERROR(cmd, "LDAPForceDefaultGID: expected boolean argument for first argument.");
1732 26
  }
1733 13
1734 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1735
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1736
  *((int *) c->argv[0]) = b;
1737
1738 28
  return PR_HANDLED(cmd);
1739 13
}
1740
1741
MODRET
1742
set_ldap_negcache(cmd_rec *cmd)
1743
{
1744 43
  pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": LDAPNegativeCache has no effect and is deprecated; please remove it from your configuration");
1745 28
  return PR_HANDLED(cmd);
1746 13
}
1747
1748
MODRET
1749 20
set_ldap_genhdir(cmd_rec *cmd)
1750 13
{
1751
  int b;
1752
  config_rec *c;
1753
1754
  CHECK_ARGS(cmd, 1);
1755
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1756
1757 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1758 20
    CONF_ERROR(cmd, "LDAPGenerateHomedir: expected a boolean value for first argument.");
1759 26
  }
1760 20
1761 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1762
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1763
  *((int *) c->argv[0]) = b;
1764 28
  return PR_HANDLED(cmd);
1765 4
}
1766
1767 20
MODRET set_ldap_forcegenhdir(cmd_rec *cmd)
1768 18
{
1769
  int b;
1770 24
  config_rec *c;
1771 18
1772
  CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1773
1774 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1775 20
    CONF_ERROR(cmd, "LDAPForceGeneratedHomedir: expected boolean argument for first argument.");
1776 26
  }
1777 18
1778 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1779
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1780
  *((int *) c->argv[0]) = b;
1781 28
  return PR_HANDLED(cmd);
1782 18
}
1783
1784 13
MODRET
1785 20
set_ldap_genhdirprefix(cmd_rec *cmd)
1786 13
{
1787
  CHECK_ARGS(cmd, 1);
1788
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1789
1790 24
  add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1791 28
  return PR_HANDLED(cmd);
1792 13
}
1793
1794
MODRET
1795 20
set_ldap_genhdirprefixnouname(cmd_rec *cmd)
1796 13
{
1797
  int b;
1798 24
  config_rec *c;
1799 13
1800
  CHECK_ARGS(cmd, 1);
1801
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1802
1803 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1804 20
    CONF_ERROR(cmd, "LDAPGenerateHomedirPrefixNoUsername: expected a boolean value for first argument.");
1805 26
  }
1806 20
1807 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1808
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1809
  *((int *) c->argv[0]) = b;
1810
1811 28
  return PR_HANDLED(cmd);
1812 13
}
1813
1814
MODRET
1815
set_ldap_defaultauthscheme(cmd_rec *cmd)
1816 4
{
1817
  CHECK_ARGS(cmd, 1);
1818
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1819
1820 24
  add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
1821 28
  return PR_HANDLED(cmd);
1822 13
}
1823
1824
MODRET
1825
set_ldap_usetls(cmd_rec *cmd)
1826
{
1827 51
#ifndef LDAP_OPT_X_TLS
1828
  CONF_ERROR(cmd, "LDAPUseTLS: Your LDAP libraries do not appear to support TLS.");
1829
#else /* LDAP_OPT_X_TLS */
1830 13
  int b;
1831 24
  config_rec *c;
1832 13
1833
  CHECK_ARGS(cmd, 1);
1834
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1835
1836 26
  if ((b = get_boolean(cmd, 1)) == -1) {
1837 13
    CONF_ERROR(cmd, "LDAPUseTLS: expected a boolean value for first argument.");
1838 26
  }
1839 13
1840 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1841
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1842
  *((int *) c->argv[0]) = b;
1843 28
  return PR_HANDLED(cmd);
1844 51
#endif /* LDAP_OPT_X_TLS */
1845 37
}
1846
1847
MODRET
1848 80
set_ldap_usessl(cmd_rec *cmd)
1849
{
1850
  pr_log_pri(PR_LOG_ERR, MOD_LDAP_VERSION ": LDAPUseSSL did not have the intended effect and has been removed. Please remove this directive from your configuration, as it will be removed in future versions of mod_ldap and ProFTPD will fail to start.");
1851 82
  return PR_HANDLED(cmd);
1852 80
}
1853
1854
MODRET
1855 20
set_ldap_protoversion(cmd_rec *cmd)
1856
{
1857
  int i = 0;
1858 24
  config_rec *c;
1859 20
1860
  CHECK_ARGS(cmd, 1);
1861
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1862
1863
  while (cmd->argv[1][i]) {
1864 26
    if (! isdigit((int) cmd->argv[1][i])) {
1865 20
      CONF_ERROR(cmd, "LDAPProtocolVersion: argument must be numeric!");
1866 26
    }
1867 20
    ++i;
1868
  }
1869
1870 24
  c = add_config_param(cmd->argv[0], 1, NULL);
1871
  c->argv[0] = pcalloc(c->pool, sizeof(int));
1872
  *((int *) c->argv[0]) = atoi(cmd->argv[1]);
1873 28
  return PR_HANDLED(cmd);
1874 20
}
1875
1876
MODRET
1877
set_ldap_attr(cmd_rec *cmd)
1878
{
1879
  CHECK_ARGS(cmd, 2);
1880
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
1881
1882
  if (strcasecmp(cmd->argv[1], "uid") != 0 &&
1883
      strcasecmp(cmd->argv[1], "uidNumber") != 0 &&
1884
      strcasecmp(cmd->argv[1], "gidNumber") != 0 &&
1885
      strcasecmp(cmd->argv[1], "homeDirectory") != 0 &&
1886
      strcasecmp(cmd->argv[1], "userPassword") != 0 &&
1887
      strcasecmp(cmd->argv[1], "loginShell") != 0 &&
1888
      strcasecmp(cmd->argv[1], "cn") != 0 &&
1889
      strcasecmp(cmd->argv[1], "memberUid") != 0 &&
1890
      strcasecmp(cmd->argv[1], "ftpQuota") != 0)
1891
  {
1892
    CONF_ERROR(cmd, "LDAPAttr: unknown attribute name.");
1893
  }
1894
1895 24
  add_config_param_str(cmd->argv[0], 2, cmd->argv[1], cmd->argv[2]);
1896 28
  return PR_HANDLED(cmd);
1897 13
}
1898
1899
static int
1900
ldap_getconf(void)
1901
{
1902 11
  char *scope;
1903 4
  config_rec *c;
1904 24
  void *ptr;
1905 4
1906 34
  /* Look up any attr redefinitions (LDAPAttr) before using those variables,
1907
   * such as when generating the default search filters.
1908 18
   */
1909 20
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPAttr", FALSE)) != NULL) {
1910
    do {
1911 26
      if (strcasecmp(c->argv[0], "uid") == 0) {
1912 23
        ldap_attr_uid = pstrdup(session.pool, c->argv[1]);
1913 26
      } else if (strcasecmp(c->argv[0], "uidNumber") == 0) {
1914 23
        ldap_attr_uidnumber = pstrdup(session.pool, c->argv[1]);
1915 26
      } else if (strcasecmp(c->argv[0], "gidNumber") == 0) {
1916 23
        ldap_attr_gidnumber = pstrdup(session.pool, c->argv[1]);
1917 26
      } else if (strcasecmp(c->argv[0], "homeDirectory") == 0) {
1918 23
        ldap_attr_homedirectory = pstrdup(session.pool, c->argv[1]);
1919 26
      } else if (strcasecmp(c->argv[0], "userPassword") == 0) {
1920 23
        ldap_attr_userpassword = pstrdup(session.pool, c->argv[1]);
1921 26
      } else if (strcasecmp(c->argv[0], "loginShell") == 0) {
1922 23
        ldap_attr_loginshell = pstrdup(session.pool, c->argv[1]);
1923 26
      } else if (strcasecmp(c->argv[0], "cn") == 0) {
1924 23
        ldap_attr_cn = pstrdup(session.pool, c->argv[1]);
1925 26
      } else if (strcasecmp(c->argv[0], "memberUid") == 0) {
1926 23
        ldap_attr_memberuid = pstrdup(session.pool, c->argv[1]);
1927 26
      } else if (strcasecmp(c->argv[0], "ftpQuota") == 0) {
1928 23
        ldap_attr_ftpquota = pstrdup(session.pool, c->argv[1]);
1929 26
      }
1930 20
    } while ((c = find_config_next(c, c->next, CONF_PARAM, "LDAPAttr", FALSE)));
1931
  }
1932 34
1933
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPDNInfo", FALSE)) != NULL) {
1934
    ldap_dn = pstrdup(session.pool, c->argv[0]);
1935
    ldap_dnpass = pstrdup(session.pool, c->argv[1]);
1936
  }
1937
1938
  ptr = get_param_ptr(main_server->conf, "LDAPAuthBinds", FALSE);
1939
  if (ptr) {
1940
    ldap_authbinds = *((int *) ptr);
1941
  }
1942
1943
  ptr = get_param_ptr(main_server->conf, "LDAPQueryTimeout", FALSE);
1944
  if (ptr) {
1945
    ldap_querytimeout = *((int *) ptr);
1946
  }
1947
1948
  scope = get_param_ptr(main_server->conf, "LDAPSearchScope", FALSE);
1949
  if (scope) {
1950
    if (strcasecmp(scope, "onelevel") == 0) {
1951
      ldap_search_scope = LDAP_SCOPE_ONELEVEL;
1952
    } else if (strcasecmp(scope, "subtree") == 0) {
1953
      ldap_search_scope = LDAP_SCOPE_SUBTREE;
1954
    }
1955
  }
1956
  
1957
  ptr = get_param_ptr(main_server->conf, "LDAPAliasDereference", FALSE);
1958
  if (ptr) {
1959
    ldap_dereference = *((int *) ptr);
1960
  }
1961
1962
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPDoAuth", FALSE)) != NULL) {
1963
    if ( *((int *) c->argv[0]) > 0) {
1964
      ldap_doauth = 1;
1965
      ldap_auth_basedn = pstrdup(session.pool, c->argv[1]);
1966
1967
      if (c->argv[2]) {
1968
        ldap_auth_filter = pstrdup(session.pool, c->argv[2]);
1969
      } else {
1970
        ldap_auth_filter = pstrcat(session.pool, "(&(", ldap_attr_uid, "=%v)(objectclass=posixAccount))", NULL);
1971
      }
1972
    }
1973
  }
1974
1975
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPDoUIDLookups", FALSE)) != NULL) {
1976
    if ( *((int *) c->argv[0]) > 0) {
1977
      ldap_douid = 1;
1978
      ldap_uid_basedn = pstrdup(session.pool, c->argv[1]);
1979
1980
      if (c->argv[2]) {
1981
        ldap_uid_filter = pstrdup(session.pool, c->argv[2]);
1982
      } else {
1983
        ldap_uid_filter = pstrcat(session.pool, "(&(", ldap_attr_uidnumber, "=%v)(objectclass=posixAccount))", NULL);
1984
      }
1985
    }
1986
  }
1987
1988
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPDoGIDLookups", FALSE)) != NULL) {
1989
    if ( *((int *) c->argv[0]) > 0) {
1990
      ldap_dogid = 1;
1991
      ldap_gid_basedn = pstrdup(session.pool, c->argv[1]);
1992
1993
      if (c->argc > 2) {
1994
        ldap_group_name_filter = pstrdup(session.pool, c->argv[2]);
1995
      } else {
1996
        ldap_group_name_filter = pstrcat(session.pool, "(&(", ldap_attr_cn, "=%v)(objectclass=posixGroup))", NULL);
1997
      }
1998
1999
      if (c->argc > 3) {
2000
        ldap_group_gid_filter = pstrdup(session.pool, c->argv[3]);
2001
      } else {
2002
        ldap_group_gid_filter = pstrcat(session.pool, "(&(", ldap_attr_gidnumber, "=%v)(objectclass=posixGroup))", NULL);
2003
      }
2004
2005
      if (c->argc > 4) {
2006
        ldap_group_member_filter = pstrdup(session.pool, c->argv[4]);
2007
      } else {
2008
        ldap_group_member_filter = pstrcat(session.pool, "(&(", ldap_attr_memberuid, "=%v)(objectclass=posixGroup))", NULL);
2009
      }
2010
    }
2011
  }
2012
2013
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPDoQuotaLookups", FALSE)) != NULL) {
2014
    if ( *((int *) c->argv[0]) > 0) {
2015
      ldap_doquota = 1;
2016
      ldap_quota_basedn = pstrdup(session.pool, c->argv[1]);
2017
2018
      if (c->argc > 2) {
2019
        ldap_quota_filter = pstrdup(session.pool, c->argv[2]);
2020
      } else {
2021
        ldap_quota_filter = pstrcat(session.pool, "(&(", ldap_attr_uid, "=%v)(objectclass=posixAccount))", NULL);
2022
      }
2023
2024
      if (c->argc > 3) {
2025
        ldap_default_quota = pstrdup(session.pool, c->argv[3]);
2026
      }
2027
    }
2028
  }
2029
2030
  ptr = get_param_ptr(main_server->conf, "LDAPDefaultUID", FALSE);
2031
  if (ptr) {
2032
    ldap_defaultuid = *((uid_t *) ptr);
2033
  }
2034
2035
  ptr = get_param_ptr(main_server->conf, "LDAPDefaultGID", FALSE);
2036
  if (ptr) {
2037
    ldap_defaultgid = *((gid_t *) ptr);
2038
  }
2039
2040
  ptr = get_param_ptr(main_server->conf, "LDAPForceDefaultUID", FALSE);
2041
  if (ptr) {
2042
    ldap_forcedefaultuid = *((int *) ptr);
2043
  }
2044
2045
  ptr = get_param_ptr(main_server->conf, "LDAPForceDefaultGID", FALSE);
2046
  if (ptr) {
2047
    ldap_forcedefaultgid = *((int *) ptr);
2048
  }
2049
2050
  ptr = get_param_ptr(main_server->conf, "LDAPForceGeneratedHomedir", FALSE);
2051
  if (ptr) {
2052
    ldap_forcegenhdir = *((int *) ptr);
2053
  }
2054
2055
  ptr = get_param_ptr(main_server->conf, "LDAPGenerateHomedir", FALSE);
2056
  if (ptr) {
2057
    ldap_genhdir = *((int *) ptr);
2058
  }
2059
2060
  ldap_genhdir_prefix = (char *)get_param_ptr(main_server->conf, "LDAPGenerateHomedirPrefix", FALSE);
2061
2062
  ptr = get_param_ptr(main_server->conf, "LDAPGenerateHomedirPrefixNoUsername", FALSE);
2063
  if (ptr) {
2064
    ldap_genhdir_prefix_nouname = *((int *) ptr);
2065
  }
2066
2067
  /* If ldap_defaultauthscheme is NULL, ldap_check() will assume crypt. */
2068
  ldap_defaultauthscheme = (char *)get_param_ptr(main_server->conf, "LDAPDefaultAuthScheme", FALSE);
2069
2070
  ptr = get_param_ptr(main_server->conf, "LDAPProtocolVersion", FALSE);
2071
  if (ptr) {
2072
    ldap_protocol_version = *((int *) ptr);
2073
  }
2074
2075 51
#ifdef LDAP_OPT_X_TLS
2076 34
  ptr = get_param_ptr(main_server->conf, "LDAPUseTLS", FALSE);
2077
  if (ptr) {
2078
    ldap_use_tls = *((int *) ptr);
2079
  }
2080 51
#endif /* LDAP_OPT_X_TLS */
2081 37
2082 38
  if ((c = find_config(main_server->conf, CONF_PARAM, "LDAPServer", FALSE)) != NULL) {
2083 77
    ldap_servers = c->argv[0];
2084
  } else {
2085
    /* Leave a NULL server entry if LDAPServer isn't present, so
2086
     * ldap_init()/ldap_initialize() will connect to the LDAP SDK's
2087
     * default.
2088
     */
2089
    ldap_servers = make_array(session.pool, 1, sizeof(char *));
2090
    *((char **)push_array(ldap_servers)) = NULL;
2091 37
  }
2092 20
2093 4
  return 0;
2094
}
2095
2096 59
static int ldap_mod_init(void) {
2097
  pr_log_debug(DEBUG2, MOD_LDAP_VERSION
2098
    ": compiled using LDAP vendor '%s', LDAP API version %lu",
2099
    LDAP_VENDOR_NAME, (unsigned long) LDAP_API_VERSION);
2100
2101
  return 0;
2102
}
2103
2104 4
static conftable ldap_config[] = {
2105 20
  { "LDAPServer",                          set_ldap_server,               NULL },
2106
  { "LDAPDNInfo",                          set_ldap_dninfo,               NULL },
2107
  { "LDAPAuthBinds",                       set_ldap_authbinds,            NULL },
2108
  { "LDAPQueryTimeout",                    set_ldap_querytimeout,         NULL },
2109
  { "LDAPSearchScope",                     set_ldap_searchscope,          NULL },
2110 23
  { "LDAPAliasDereference",                set_ldap_dereference,          NULL },
2111 20
  { "LDAPNegativeCache",                   set_ldap_negcache,             NULL },
2112
  { "LDAPDoAuth",                          set_ldap_doauth,               NULL },
2113
  { "LDAPDoUIDLookups",                    set_ldap_douid,                NULL },
2114
  { "LDAPDoGIDLookups",                    set_ldap_dogid,                NULL },
2115
  { "LDAPDoQuotaLookups",                  set_ldap_doquota,              NULL },
2116
  { "LDAPDefaultUID",                      set_ldap_defaultuid,           NULL },
2117
  { "LDAPDefaultGID",                      set_ldap_defaultgid,           NULL },
2118
  { "LDAPForceDefaultUID",                 set_ldap_forcedefaultuid,      NULL },
2119
  { "LDAPForceDefaultGID",                 set_ldap_forcedefaultgid,      NULL },
2120
  { "LDAPGenerateHomedir",                 set_ldap_genhdir,              NULL },
2121
  { "LDAPGenerateHomedirPrefix",           set_ldap_genhdirprefix,        NULL },
2122
  { "LDAPGenerateHomedirPrefixNoUsername", set_ldap_genhdirprefixnouname, NULL },
2123
  { "LDAPForceGeneratedHomedir",           set_ldap_forcegenhdir,         NULL },
2124
  { "LDAPDefaultAuthScheme",               set_ldap_defaultauthscheme,    NULL },
2125
  { "LDAPUseTLS",                          set_ldap_usetls,               NULL },
2126 80
  { "LDAPUseSSL",                          set_ldap_usessl,               NULL },
2127 20
  { "LDAPProtocolVersion",                 set_ldap_protoversion,         NULL },
2128
  { "LDAPAttr",                            set_ldap_attr,                 NULL },
2129
  { NULL,                                  NULL,                          NULL }
2130 4
};
2131
2132 18
static cmdtable ldap_cmdtab[] = {
2133 20
  {HOOK, "ldap_quota_lookup", G_NONE, handle_ldap_quota_lookup, FALSE, FALSE},
2134 18
  {0, NULL}
2135
};
2136
2137 4
static authtable ldap_auth[] = {
2138 16
  { 0, "setpwent",  handle_ldap_setpwent  },
2139
  { 0, "endpwent",  handle_ldap_endpwent  },
2140
  { 0, "setgrent",  handle_ldap_setpwent  },
2141
  { 0, "endgrent",  handle_ldap_endpwent  },
2142
  { 0, "getpwnam",  handle_ldap_getpwnam  },
2143
  { 0, "getpwuid",  handle_ldap_getpwuid  },
2144
  { 0, "getgrnam",  handle_ldap_getgrnam  },
2145
  { 0, "getgrgid",  handle_ldap_getgrgid  },
2146
  { 0, "auth",      handle_ldap_is_auth   },
2147
  { 0, "check",     handle_ldap_check     },
2148 20
  { 0, "uid2name",  handle_ldap_uid_name  },
2149
  { 0, "gid2name",  handle_ldap_gid_name  },
2150
  { 0, "name2uid",  handle_ldap_name_uid  },
2151
  { 0, "name2gid",  handle_ldap_name_gid  },
2152 16
  { 0, "getgroups", handle_ldap_getgroups },
2153
  { 0, NULL }
2154 4
};
2155
2156
module ldap_module = {
2157 43
  NULL, NULL,          /* Always NULL */
2158
  0x20,                /* API Version 2.0 */
2159 4
  "ldap",
2160 43
  ldap_config,         /* Configuration directive table */
2161
  ldap_cmdtab,         /* Command handlers */
2162
  ldap_auth,           /* Authentication handlers */
2163 59
  ldap_mod_init,       /* Initialization functions */
2164
  ldap_getconf,
2165 20
  MOD_LDAP_VERSION
2166 4
};

Loggerhead 1.17 is a web-based interface for Bazaar branches