View | Details | Raw Unified | Return to bug 38515
Collapse All | Expand All

(-)include/util_ldap.h (+18 lines)
Lines 303-309 Link Here
303
                              const char *url, const char *basedn, int scope, char **attrs,
303
                              const char *url, const char *basedn, int scope, char **attrs,
304
                              const char *filter, const char **binddn, const char ***retvals));
304
                              const char *filter, const char **binddn, const char ***retvals));
305
305
306
306
/**
307
/**
308
 * Retrieve the values of a specific attribute on a given DN.
309
 * @param r The request record
310
 * @param ldc The LDAP connection being used.
311
 * @param url The URL of the LDAP connection - used for deciding which cache to use.
312
 * @param dn The Base DN to search for the user in.
313
 * @param attrib The LDAP attribute name to return in search.
314
 * @param values On success, *values is set to a NULL-terminated array of attribute values,
315
 *               values[0] through values[n] == NULL
316
 * @deffunc int util_ldap_cache_getattrvals(request_rec *r, util_ldap_connection_t *ldc,
317
 *                                          const char *url, const char *dn,
318
 *                                          const char *attrib, const char ***values)
319
 */
320
APR_DECLARE_OPTIONAL_FN(int,uldap_cache_getattrvals,(request_rec *r, util_ldap_connection_t *ldc,
321
                                                     const char *url, const char *dn, 
322
                                                     const char *attrib, const char ***values));
323
324
/**
307
 * Checks if SSL support is available in mod_ldap
325
 * Checks if SSL support is available in mod_ldap
308
 * @deffunc int util_ldap_ssl_supported(request_rec *r)
326
 * @deffunc int util_ldap_ssl_supported(request_rec *r)
309
 */
327
 */
(-)modules/ldap/util_ldap.c (+73 lines)
Lines 1321-1326 Link Here
1321
    return LDAP_SUCCESS;
1321
    return LDAP_SUCCESS;
1322
}
1322
}
1323
1323
1324
static int uldap_cache_getattrvals(request_rec *r, 
1325
                                   util_ldap_connection_t *ldc,
1326
                                   const char *url, const char *dn,
1327
                                   const char *attrib,
1328
                                   const char ***values)
1329
{
1330
    int failures = 0, result, n, count;
1331
    LDAPMessage *res, *entry;
1332
    char **attrs, **vals;
1333
1334
    attrs = apr_pcalloc(r->pool, 2 * sizeof *attrs);
1335
    attrs[0] = (char *)attrib;
1336
1337
start_over:
1338
    if (failures++ > 10) {
1339
        /* too many failures */
1340
        return result;
1341
    }
1342
1343
    result = uldap_connection_open(r, ldc);
1344
    if (result != LDAP_SUCCESS) {
1345
        return result;
1346
    }
1347
1348
    result = ldap_search_ext_s(ldc->ldap, dn, LDAP_SCOPE_BASE,
1349
                               "(objectclass=*)", attrs, 0,
1350
                               NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res);
1351
    if (AP_LDAP_IS_SERVER_DOWN(result)) {
1352
        ldc->reason = "DN Comparison ldap_search_ext_s() "
1353
                      "failed with server down";
1354
        uldap_connection_unbind(ldc);
1355
        goto start_over;
1356
    }
1357
1358
    if (result != LDAP_SUCCESS) {
1359
        ldc->reason = "DN attribute fetch ldap_search_ext_s() failed";
1360
        return result;
1361
    }
1362
    
1363
    /* Require exactly one entry to be returned. */
1364
    count = ldap_count_entries(ldc->ldap, res);
1365
    if (count != 1) {
1366
        ldc->reason = apr_psprintf(r->pool, "found %d entries, expected "
1367
                                   "exactly one match", count);
1368
        ldap_msgfree(res);
1369
        return LDAP_NO_SUCH_OBJECT;
1370
    }
1371
1372
    entry = ldap_first_entry(ldc->ldap, res);
1373
1374
    vals = ldap_get_values(ldc->ldap, entry, attrib);
1375
    if (!vals) {
1376
        ldap_memfree(res);
1377
        ldc->reason = "ldap_get_values() failed";
1378
        return LDAP_NO_SUCH_OBJECT;
1379
    }
1380
    
1381
    count = ldap_count_values(vals);
1382
1383
    /* Duplicate into pool space. */
1384
    *values = apr_palloc(r->pool, (count + 1) * sizeof **values);
1385
    for (n = 0; n < count; n++) {
1386
        (*values)[n] = apr_pstrdup(r->pool, vals[n]);
1387
    }
1388
    values[n] = NULL;
1389
1390
    ldap_value_free(vals);
1391
    ldap_memfree(res);
1392
1393
    return LDAP_SUCCESS;
1394
}
1395
1324
/*
1396
/*
1325
 * Reports if ssl support is enabled
1397
 * Reports if ssl support is enabled
1326
 *
1398
 *
Lines 2143-2148 Link Here
2143
    APR_REGISTER_OPTIONAL_FN(uldap_connection_find);
2215
    APR_REGISTER_OPTIONAL_FN(uldap_connection_find);
2144
    APR_REGISTER_OPTIONAL_FN(uldap_cache_comparedn);
2216
    APR_REGISTER_OPTIONAL_FN(uldap_cache_comparedn);
2145
    APR_REGISTER_OPTIONAL_FN(uldap_cache_compare);
2217
    APR_REGISTER_OPTIONAL_FN(uldap_cache_compare);
2218
    APR_REGISTER_OPTIONAL_FN(uldap_cache_getattrvals);
2146
    APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);
2219
    APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);
2147
    APR_REGISTER_OPTIONAL_FN(uldap_cache_getuserdn);
2220
    APR_REGISTER_OPTIONAL_FN(uldap_cache_getuserdn);
2148
    APR_REGISTER_OPTIONAL_FN(uldap_ssl_supported);
2221
    APR_REGISTER_OPTIONAL_FN(uldap_ssl_supported);
(-)modules/aaa/mod_authnz_ldap.c (-3 / +117 lines)
Lines 74-79 Link Here
74
    int group_attrib_is_dn;         /* If true, the group attribute is the DN, otherwise,
74
    int group_attrib_is_dn;         /* If true, the group attribute is the DN, otherwise,
75
                                        it's the exact string passed by the HTTP client */
75
                                        it's the exact string passed by the HTTP client */
76
76
77
    int dynamic_groups;             /* If true, dynamic group lookups are enabled. */
78
77
    int secure;                     /* True if SSL connections are requested */
79
    int secure;                     /* True if SSL connections are requested */
78
} authn_ldap_config_t;
80
} authn_ldap_config_t;
79
81
Lines 95-100 Link Here
95
static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
97
static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
96
static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
98
static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
97
static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
99
static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
100
static APR_OPTIONAL_FN_TYPE(uldap_cache_getattrvals) *util_ldap_cache_getattrvals;
98
static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
101
static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
99
static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
102
static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
100
static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
103
static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
Lines 102-107 Link Here
102
static apr_hash_t *charset_conversions = NULL;
105
static apr_hash_t *charset_conversions = NULL;
103
static char *to_charset = NULL;           /* UTF-8 identifier derived from the charset.conv file */
106
static char *to_charset = NULL;           /* UTF-8 identifier derived from the charset.conv file */
104
107
108
/* Evaluates to a string description of a scope integer. */
109
#define SCOPE_TO_STR(scope_)                                    \
110
    (scope_ == LDAP_SCOPE_SUBTREE? "subtree" :                  \
111
     scope_ == LDAP_SCOPE_BASE? "base" :                        \
112
     scope_ == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown")
105
113
106
/* Derive a code page ID give a language name or ID */
114
/* Derive a code page ID give a language name or ID */
107
static char* derive_codepage_from_lang (apr_pool_t *p, char *language)
115
static char* derive_codepage_from_lang (apr_pool_t *p, char *language)
Lines 477-482 Link Here
477
    return AUTH_GRANTED;
485
    return AUTH_GRANTED;
478
}
486
}
479
487
488
/* Check whether user is a member of dynamic group groupDN.  Returns
489
 * LDAP_COMPARE_TRUE on success or LDAP_COMPARE_FALSE otherwise.  */
490
static int check_dynamic_groups(request_rec *r, util_ldap_connection_t *ldc,
491
                                authn_ldap_config_t *sec, authn_ldap_request_t *req,
492
                                const char *attrib, const char *groupDN)
493
{
494
    apr_ldap_url_desc_t *gurl;
495
    apr_ldap_err_t *err;
496
    const char **vals;
497
    int result, n;
498
499
    /* Retrieve the set of memberURL attribute values from the group
500
     * DN which specify the search URLs which define the group. */
501
    result = util_ldap_cache_getattrvals(r, ldc, sec->url, groupDN, attrib, &vals);
502
    if (result != LDAP_SUCCESS) {
503
        return LDAP_COMPARE_FALSE;
504
    }
505
506
    /* Iterate through the returned search URLs attempting to match
507
     * the user's DN against the results of each search.  */
508
    for (n = 0, result = LDAP_COMPARE_FALSE; 
509
         vals[n] && result != LDAP_COMPARE_TRUE; 
510
         n++) {
511
        char filter[FILTER_LENGTH];
512
        const char *dn;
513
514
        /* Parse the URL. */
515
        result = apr_ldap_url_parse(r->pool, vals[n], &gurl, &err);
516
        if (result) {
517
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
518
                          "auth_ldap authorise: could not parse URL %s for dynamic group",
519
                          vals[n]);
520
            result = LDAP_COMPARE_FALSE;
521
            ldc->reason = "could not parse URL";
522
            continue;
523
        }
524
        
525
        /* The host and attribute fields will be ignored so warn if
526
         * they are specified. */
527
        if (gurl->lud_host || gurl->lud_attrs) {
528
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
529
                          "auth_ldap authorise: attrib/host are ignored in dynamic group URL %s",
530
                          vals[n]);
531
        }
532
533
        /* Build the search filter; a boolean AND of the group's
534
         * search filter and a search filter for the user. */
535
        authn_ldap_build_filter(filter, r, req->user, gurl->lud_filter, sec);
536
537
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
538
                      "auth_ldap authorise: checking dynamic group ldap:///%s?%s?%s",
539
                      gurl->lud_dn, SCOPE_TO_STR(gurl->lud_scope), filter);
540
541
        /* Search for the user DN. */
542
        result = util_ldap_cache_getuserdn(r, ldc, sec->url, 
543
                                           gurl->lud_dn, gurl->lud_scope, NULL, 
544
                                           filter, &dn, &vals);
545
        if (result == LDAP_SUCCESS) {
546
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
547
                          "[%" APR_PID_T_FMT "] auth_ldap authorise: checking "
548
                          "DN %s match for dynamic group",
549
                          getpid(), dn);
550
            result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, dn,
551
                                               sec->compare_dn_on_server);
552
        }
553
        
554
        if (result != LDAP_COMPARE_TRUE) {
555
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
556
                          "[%" APR_PID_T_FMT "] auth_ldap authorise: failed to find user DN "
557
                          "in dynamic group %s",
558
                          getpid(), vals[n]);
559
            result = LDAP_COMPARE_FALSE;
560
        }
561
    }
562
563
    return result;
564
}
565
480
/*
566
/*
481
 * Authorisation Phase
567
 * Authorisation Phase
482
 * -------------------
568
 * -------------------
Lines 755-760 Link Here
755
                    }
841
                    }
756
                }
842
                }
757
            }
843
            }
844
845
            if (sec->dynamic_groups) {
846
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
847
                              "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: "
848
                              "testing for dynamic group membership in \"%s\"",
849
                              getpid(), t);
850
                result = check_dynamic_groups(r, ldc, sec, req, "memberURL", t);
851
                
852
                switch (result) {
853
                case LDAP_COMPARE_TRUE:
854
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
855
                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: require dynamic group: "
856
                                  "authorisation successful [%s][%s]",
857
                                  getpid(), ldc->reason, ldap_err2string(result));
858
                    return OK;
859
                default:
860
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
861
                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: require dynamic group \"%s\": "
862
                                  "authorisation failed [%s][%s]",
863
                                  getpid(), t, ldc->reason, ldap_err2string(result));
864
                    break;
865
                }
866
            }
758
        }
867
        }
759
        else if (strcmp(w, "ldap-attribute") == 0) {
868
        else if (strcmp(w, "ldap-attribute") == 0) {
760
            if (req->dn == NULL || strlen(req->dn) == 0) {
869
            if (req->dn == NULL || strlen(req->dn) == 0) {
Lines 977-985 Link Here
977
                 urld->lud_port,
1086
                 urld->lud_port,
978
                 urld->lud_dn,
1087
                 urld->lud_dn,
979
                 urld->lud_attrs? urld->lud_attrs[0] : "(null)",
1088
                 urld->lud_attrs? urld->lud_attrs[0] : "(null)",
980
                 (urld->lud_scope == LDAP_SCOPE_SUBTREE? "subtree" :
1089
                 SCOPE_TO_STR(urld->lud_scope),
981
                  urld->lud_scope == LDAP_SCOPE_BASE? "base" :
982
                  urld->lud_scope == LDAP_SCOPE_ONELEVEL? "onelevel" : "unknown"),
983
                 urld->lud_filter,
1090
                 urld->lud_filter,
984
                 sec->secure == APR_LDAP_SSL  ? "using SSL": "not using SSL"
1091
                 sec->secure == APR_LDAP_SSL  ? "using SSL": "not using SSL"
985
                 );
1092
                 );
Lines 1100-1105 Link Here
1100
                 "subsequent group comparisons. If set to 'off', auth_ldap uses the string"
1207
                 "subsequent group comparisons. If set to 'off', auth_ldap uses the string"
1101
                 "provided by the client directly. Defaults to 'on'."),
1208
                 "provided by the client directly. Defaults to 'on'."),
1102
1209
1210
    AP_INIT_FLAG("AuthLDAPDynamicGroupLookup", ap_set_flag_slot,
1211
                 (void *)APR_OFFSETOF(authn_ldap_config_t, dynamic_groups), OR_AUTHCFG,
1212
                 "If set to 'on', auth_ldap will look for dynamic group URI in a group DN "
1213
                 "and attempt to see if a user is part of a group defined by that URI "
1214
                 "Defaults to 'off'."),
1215
1103
    AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG,
1216
    AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG,
1104
                  "Determines how aliases are handled during a search. Can bo one of the"
1217
                  "Determines how aliases are handled during a search. Can bo one of the"
1105
                  "values \"never\", \"searching\", \"finding\", or \"always\". "
1218
                  "values \"never\", \"searching\", \"finding\", or \"always\". "
Lines 1212-1217 Link Here
1212
    util_ldap_connection_find   = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
1325
    util_ldap_connection_find   = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
1213
    util_ldap_cache_comparedn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
1326
    util_ldap_cache_comparedn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
1214
    util_ldap_cache_compare     = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
1327
    util_ldap_cache_compare     = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
1328
    util_ldap_cache_getattrvals = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getattrvals);
1215
    util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
1329
    util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
1216
    util_ldap_cache_getuserdn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
1330
    util_ldap_cache_getuserdn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
1217
    util_ldap_ssl_supported     = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
1331
    util_ldap_ssl_supported     = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);

Return to bug 38515