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

(-)httpd-trunk/modules/ldap/util_ldap_cache.c (-2 / +26 lines)
Lines 259-270 Link Here
259
    if (node) {
259
    if (node) {
260
        if (!(node->dn = util_ald_strdup(cache, n->dn)) ||
260
        if (!(node->dn = util_ald_strdup(cache, n->dn)) ||
261
            !(node->attrib = util_ald_strdup(cache, n->attrib)) ||
261
            !(node->attrib = util_ald_strdup(cache, n->attrib)) ||
262
            !(node->value = util_ald_strdup(cache, n->value))) {
262
            !(node->value = util_ald_strdup(cache, n->value)) ||
263
            ((n->subgroupList) && !(node->subgroupList = util_ald_sgl_dup(cache, n->subgroupList)))) {
263
            util_ldap_compare_node_free(cache, node);
264
            util_ldap_compare_node_free(cache, node);
264
            return NULL;
265
            return NULL;
265
        }
266
        }
266
        node->lastcompare = n->lastcompare;
267
        node->lastcompare = n->lastcompare;
267
        node->result = n->result;
268
        node->result = n->result;
269
        node->sgl_processed = n->sgl_processed;
268
        return node;
270
        return node;
269
    }
271
    }
270
    else {
272
    else {
Lines 275-280 Link Here
275
void util_ldap_compare_node_free(util_ald_cache_t *cache, void *n)
277
void util_ldap_compare_node_free(util_ald_cache_t *cache, void *n)
276
{
278
{
277
    util_compare_node_t *node = n;
279
    util_compare_node_t *node = n;
280
281
    util_ald_sgl_free(cache, &(node->subgroupList));
278
    util_ald_free(cache, node->dn);
282
    util_ald_free(cache, node->dn);
279
    util_ald_free(cache, node->attrib);
283
    util_ald_free(cache, node->attrib);
280
    util_ald_free(cache, node->value);
284
    util_ald_free(cache, node->value);
Lines 286-291 Link Here
286
    util_compare_node_t *node = n;
290
    util_compare_node_t *node = n;
287
    char date_str[APR_CTIME_LEN+1];
291
    char date_str[APR_CTIME_LEN+1];
288
    char *cmp_result;
292
    char *cmp_result;
293
    char *sub_groups_val;
294
    char *sub_groups_checked;
289
295
290
    apr_ctime(date_str, node->lastcompare);
296
    apr_ctime(date_str, node->lastcompare);
291
297
Lines 299-304 Link Here
299
        cmp_result = apr_itoa(r->pool, node->result);
305
        cmp_result = apr_itoa(r->pool, node->result);
300
    }
306
    }
301
307
308
    if(node->subgroupList) {
309
        sub_groups_val = "Yes";
310
    }
311
    else {
312
        sub_groups_val = "No";
313
    }
314
315
    if(node->sgl_processed) {
316
        sub_groups_checked = "Yes";
317
    }
318
    else {
319
        sub_groups_checked = "No";
320
    }
321
302
    ap_rprintf(r,
322
    ap_rprintf(r,
303
               "<tr valign='top'>"
323
               "<tr valign='top'>"
304
               "<td nowrap>%s</td>"
324
               "<td nowrap>%s</td>"
Lines 306-317 Link Here
306
               "<td nowrap>%s</td>"
326
               "<td nowrap>%s</td>"
307
               "<td nowrap>%s</td>"
327
               "<td nowrap>%s</td>"
308
               "<td nowrap>%s</td>"
328
               "<td nowrap>%s</td>"
329
               "<td nowrap>%s</td>"
330
               "<td nowrap>%s</td>"
309
               "</tr>",
331
               "</tr>",
310
               node->dn,
332
               node->dn,
311
               node->attrib,
333
               node->attrib,
312
               node->value,
334
               node->value,
313
               date_str,
335
               date_str,
314
               cmp_result);
336
               cmp_result,
337
               sub_groups_val,
338
               sub_groups_checked);
315
}
339
}
316
340
317
/* ------------------------------------------------------------------ */
341
/* ------------------------------------------------------------------ */
(-)httpd-trunk/modules/ldap/util_ldap_cache.h (+12 lines)
Lines 97-102 Link Here
97
} util_url_node_t;
97
} util_url_node_t;
98
98
99
/*
99
/*
100
 * When a group is found, subgroups are stored in the group's cache entry.
101
 */
102
typedef struct util_compare_subgroup_t {
103
    const char **subgroupDNs;
104
    int len;
105
} util_compare_subgroup_t;
106
107
/*
100
 * We cache every successful search and bind operation, using the username 
108
 * We cache every successful search and bind operation, using the username 
101
 * as the key. Each node in the cache contains the returned DN, plus the 
109
 * as the key. Each node in the cache contains the returned DN, plus the 
102
 * password used to bind.
110
 * password used to bind.
Lines 121-126 Link Here
121
    const char *value;
129
    const char *value;
122
    apr_time_t lastcompare;
130
    apr_time_t lastcompare;
123
    int result;
131
    int result;
132
    int sgl_processed;      /* 0 if no sgl processing yet. 1 if sgl has been processed (even if SGL is NULL). Saves repeat work on leaves. */
133
    struct util_compare_subgroup_t *subgroupList;
124
} util_compare_node_t;
134
} util_compare_node_t;
125
135
126
/*
136
/*
Lines 169-174 Link Here
169
void util_ald_free(util_ald_cache_t *cache, const void *ptr);
179
void util_ald_free(util_ald_cache_t *cache, const void *ptr);
170
void *util_ald_alloc(util_ald_cache_t *cache, unsigned long size);
180
void *util_ald_alloc(util_ald_cache_t *cache, unsigned long size);
171
const char *util_ald_strdup(util_ald_cache_t *cache, const char *s);
181
const char *util_ald_strdup(util_ald_cache_t *cache, const char *s);
182
util_compare_subgroup_t *util_ald_sgl_dup(util_ald_cache_t *cache, util_compare_subgroup_t *sgl);
183
void util_ald_sgl_free(util_ald_cache_t *cache, util_compare_subgroup_t **sgl);
172
184
173
/* Cache managing function */
185
/* Cache managing function */
174
unsigned long util_ald_hash_string(int nstr, ...);
186
unsigned long util_ald_hash_string(int nstr, ...);
(-)httpd-trunk/modules/ldap/util_ldap_cache_mgr.c (-2 / +44 lines)
Lines 126-132 Link Here
126
        else {
126
        else {
127
            return NULL;
127
            return NULL;
128
        }
128
        }
129
    } else {
129
    }
130
    else {
130
        /* Cache shm is not used */
131
        /* Cache shm is not used */
131
        return strdup(s);
132
        return strdup(s);
132
    }
133
    }
Lines 135-142 Link Here
135
#endif
136
#endif
136
}
137
}
137
138
139
/*
140
 * Duplicate a subgroupList from one compare entry to another.
141
 * Returns: ptr to a new copy of the subgroupList or NULL if allocation failed.
142
 */
143
util_compare_subgroup_t *util_ald_sgl_dup(util_ald_cache_t *cache, util_compare_subgroup_t *sgl_in)
144
{
145
    int i = 0;
146
    util_compare_subgroup_t *sgl_out = NULL;
138
147
148
    if (!sgl_in) return NULL;
149
150
    sgl_out = (util_compare_subgroup_t *) util_ald_alloc(cache, sizeof(util_compare_subgroup_t));
151
    sgl_out->subgroupDNs = util_ald_alloc(cache, sizeof(char *) * sgl_in->len);
152
    sgl_out->len = sgl_in->len;
153
154
    for (i = 0; i < sgl_in->len; i++) {
155
        fprintf(stderr, "sgl_dup: Adding %s to sgl\n", sgl_in->subgroupDNs[i]); fflush(stderr);
156
        sgl_out->subgroupDNs[i] = util_ald_strdup(cache, sgl_in->subgroupDNs[i]);
157
    }
158
159
    return sgl_out;
160
}
161
139
/*
162
/*
163
 * Delete an entire subgroupList.
164
 */
165
void util_ald_sgl_free(util_ald_cache_t *cache, util_compare_subgroup_t **sgl)
166
{
167
    int i = 0;
168
    if (sgl == NULL || *sgl == NULL) {
169
        return;
170
    }
171
172
    for (i = 0; i < (*sgl)->len; i++) {
173
        util_ald_free(cache, (*sgl)->subgroupDNs[i]);
174
    }
175
    util_ald_free(cache, *sgl);
176
}
177
178
/*
140
 * Computes the hash on a set of strings. The first argument is the number
179
 * Computes the hash on a set of strings. The first argument is the number
141
 * of strings to hash, the rest of the args are strings.
180
 * of strings to hash, the rest of the args are strings.
142
 * Algorithm taken from glibc.
181
 * Algorithm taken from glibc.
Lines 365-373 Link Here
365
    cache->fetches++;
404
    cache->fetches++;
366
405
367
    hashval = (*cache->hash)(payload) % cache->size;
406
    hashval = (*cache->hash)(payload) % cache->size;
407
368
    for (p = cache->nodes[hashval];
408
    for (p = cache->nodes[hashval];
369
         p && !(*cache->compare)(p->payload, payload);
409
         p && !(*cache->compare)(p->payload, payload);
370
    p = p->next) ;
410
         p = p->next) ;
371
411
372
    if (p != NULL) {
412
    if (p != NULL) {
373
        cache->hits++;
413
        cache->hits++;
Lines 676-681 Link Here
676
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Value</b></font></td>"
716
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Value</b></font></td>"
677
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Compare</b></font></td>"
717
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Last Compare</b></font></td>"
678
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Result</b></font></td>"
718
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Result</b></font></td>"
719
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>Sub-groups?</b></font></td>"
720
                             "<td><font size='-1' face='Arial,Helvetica' color='#ffffff'><b>S-G Checked?</b></font></td>"
679
                             "</tr>\n", r
721
                             "</tr>\n", r
680
                            );
722
                            );
681
                    if (n) {
723
                    if (n) {
(-)httpd-trunk/modules/ldap/util_ldap.c (-7 / +305 lines)
Lines 748-753 Link Here
748
        the_compare_node.attrib = (char *)attrib;
748
        the_compare_node.attrib = (char *)attrib;
749
        the_compare_node.value = (char *)value;
749
        the_compare_node.value = (char *)value;
750
        the_compare_node.result = 0;
750
        the_compare_node.result = 0;
751
        the_compare_node.sgl_processed = 0;
752
        the_compare_node.subgroupList = NULL;
751
753
752
        compare_nodep = util_ald_cache_fetch(curl->compare_cache,
754
        compare_nodep = util_ald_cache_fetch(curl->compare_cache,
753
                                             &the_compare_node);
755
                                             &the_compare_node);
Lines 760-783 Link Here
760
            }
762
            }
761
            else {
763
            else {
762
                /* ...and it is good */
764
                /* ...and it is good */
763
                /* unlock this read lock */
764
                LDAP_CACHE_UNLOCK();
765
                if (LDAP_COMPARE_TRUE == compare_nodep->result) {
765
                if (LDAP_COMPARE_TRUE == compare_nodep->result) {
766
                    ldc->reason = "Comparison true (cached)";
766
                    ldc->reason = "Comparison true (cached)";
767
                    return compare_nodep->result;
768
                }
767
                }
769
                else if (LDAP_COMPARE_FALSE == compare_nodep->result) {
768
                else if (LDAP_COMPARE_FALSE == compare_nodep->result) {
770
                    ldc->reason = "Comparison false (cached)";
769
                    ldc->reason = "Comparison false (cached)";
771
                    return compare_nodep->result;
772
                }
770
                }
773
                else if (LDAP_NO_SUCH_ATTRIBUTE == compare_nodep->result) {
771
                else if (LDAP_NO_SUCH_ATTRIBUTE == compare_nodep->result) {
774
                    ldc->reason = "Comparison no such attribute (cached)";
772
                    ldc->reason = "Comparison no such attribute (cached)";
775
                    return compare_nodep->result;
776
                }
773
                }
777
                else {
774
                else {
778
                    ldc->reason = "Comparison undefined (cached)";
775
                    ldc->reason = "Comparison undefined (cached)";
779
                    return compare_nodep->result;
780
                }
776
                }
777
778
                /* record the result code to return with the reason... */
779
                result = compare_nodep->result;
780
                /* and unlock this read lock */
781
                LDAP_CACHE_UNLOCK();
782
                return result;
781
            }
783
            }
782
        }
784
        }
783
        /* unlock this read lock */
785
        /* unlock this read lock */
Lines 789-794 Link Here
789
        /* too many failures */
791
        /* too many failures */
790
        return result;
792
        return result;
791
    }
793
    }
794
792
    if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
795
    if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
793
        /* connect failed */
796
        /* connect failed */
794
        return result;
797
        return result;
Lines 814-819 Link Here
814
            LDAP_CACHE_LOCK();
817
            LDAP_CACHE_LOCK();
815
            the_compare_node.lastcompare = curtime;
818
            the_compare_node.lastcompare = curtime;
816
            the_compare_node.result = result;
819
            the_compare_node.result = result;
820
            the_compare_node.sgl_processed = 0;
821
            the_compare_node.subgroupList = NULL;
817
822
818
            /* If the node doesn't exist then insert it, otherwise just update
823
            /* If the node doesn't exist then insert it, otherwise just update
819
             * it with the last results
824
             * it with the last results
Lines 825-831 Link Here
825
                || (strcmp(the_compare_node.attrib,compare_nodep->attrib) != 0)
830
                || (strcmp(the_compare_node.attrib,compare_nodep->attrib) != 0)
826
                || (strcmp(the_compare_node.value, compare_nodep->value) != 0))
831
                || (strcmp(the_compare_node.value, compare_nodep->value) != 0))
827
            {
832
            {
828
                util_ald_cache_insert(curl->compare_cache, &the_compare_node);
833
                void *junk;
834
835
                junk = util_ald_cache_insert(curl->compare_cache, &the_compare_node);
836
                if(junk == NULL) {
837
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "[%" APR_PID_T_FMT "] cache_compare: Cache insertion failure.", getpid());
838
                }
829
            }
839
            }
830
            else {
840
            else {
831
                compare_nodep->lastcompare = curtime;
841
                compare_nodep->lastcompare = curtime;
Lines 849-854 Link Here
849
    return result;
859
    return result;
850
}
860
}
851
861
862
/*
863
 * Does a recursive lookup operation to try to find a user within (cached) nested
864
 * groups. It accepts a cache that it will use to lookup previous compare attempts.
865
 * We cache two kinds of compares (require group compares) and (require user
866
 * compares). Each compare has a different cache node: require group includes the DN;
867
 * require user does not because the require user cache is owned by the
868
 *
869
 * DON'T CALL THIS UNLESS YOU CALLED uldap_cache_compare FIRST!!!!!
870
 */
871
static int uldap_cache_check_subgroups(request_rec *r, util_ldap_connection_t *ldc,
872
                                       const char *url, const char *dn,
873
                                       const char *attrib, const char *value,
874
                                       char **subgroupAttrs, apr_array_header_t *subgroupclasses,
875
                                       int cur_subgroup_depth, int max_subgroup_depth)
876
{
877
    int result = LDAP_COMPARE_FALSE;
878
    util_url_node_t *curl;
879
    util_url_node_t curnode;
880
    util_compare_node_t *compare_nodep;
881
    util_compare_node_t the_compare_node;
882
    util_compare_subgroup_t *tmp_local_sgl = NULL;
883
    int failures = 0;
884
    LDAPMessage *sga_res, *entry;
885
    apr_array_header_t *subgroups = apr_array_make(r->pool, 20, sizeof(char *));
886
887
    util_ldap_state_t *st = (util_ldap_state_t *)
888
                            ap_get_module_config(r->server->module_config,
889
                                                 &ldap_module);
890
891
    /*
892
     * 1. Call uldap_cache_compare for each subgroupclass value to check the generic,
893
     *    user-agnostic, cached group entry. This will create a new generic cache entry if there
894
     *    wasn't one. If nothing returns LDAP_COMPARE_TRUE skip to step 5 since we have no groups.
895
     * 2. Lock The cache and get the generic cache entry.
896
     * 3. Check if there is already a subgrouplist in this generic group's cache entry.
897
     *    A. If there is, go to step 4.
898
     *    B. If there isn't:
899
     *       i) Use ldap_search to get the full list
900
     *          of subgroup "members" (which may include non-group "members").
901
     *       ii) Use uldap_cache_compare to strip the list down to just groups.
902
     *       iii) Lock and add this stripped down list to the cache of the generic group.
903
     * 4. Loop through the sgl and call uldap_cache_compare (using the user info) for each
904
     *    subgroup to see if the subgroup contains the user and to get the subgroups added to the
905
     *    cache (with user-afinity, if they aren't already there).
906
     *    A. If the user is in the subgroup, then we'll be returning LDAP_COMPARE_TRUE.
907
     *    B. if the user isn't in the subgroup (LDAP_COMPARE_FALSE via uldap_cache_compare) then
908
     *       recursively call this function to get the sub-subgroups added...
909
     * 5. Cleanup local allocations.
910
     * 6. Return the final result.
911
     */
912
913
        /* Stop looking at deeper levels of nested groups if we have reached the max.
914
         * Since we already checked the top-level group in uldap_cache_compare, we don't
915
         * need to check it again here - so if max_subgroup_depth is set to 0, we won't
916
         * check it (i.e. that is why we check < rather than <=).
917
         * We'll be calling uldap_cache_compare from here to check if the user is in the
918
         * next level before we recurse into that next level looking for more subgroups.
919
         */
920
    if (cur_subgroup_depth < max_subgroup_depth) {
921
        int base_sgcIndex = 0;
922
        int lcl_sgl_processedFlag = 0;
923
        struct mod_auth_ldap_groupattr_entry_t *sgc_ents = (struct mod_auth_ldap_groupattr_entry_t *) subgroupclasses->elts;
924
925
        /* 1. Check the "groupiness" of the specified basedn. Stopping at the first TRUE return. */
926
        while ((base_sgcIndex < subgroupclasses->nelts) && (result != LDAP_COMPARE_TRUE)) {
927
            result = uldap_cache_compare(r, ldc, url, dn, "objectClass", sgc_ents[base_sgcIndex].name);
928
            if (result != LDAP_COMPARE_TRUE) {
929
                base_sgcIndex++;
930
            }
931
        }
932
933
        if (result != LDAP_COMPARE_TRUE) {
934
            /* The dn we were handed doesn't seem to be a group, how can we check for SUB-groups if this
935
             * isn't a group?!?!?!
936
             */
937
            ldc->reason = "DN failed group verification.";
938
            return result;
939
        }
940
941
        /* 2. Find previously created cache entry and check if there is already a subgrouplist. */
942
        LDAP_CACHE_LOCK();
943
        curnode.url = url;
944
        curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
945
        LDAP_CACHE_UNLOCK();
946
947
        if (curl && curl->compare_cache) {
948
            /* make a comparison to the cache */
949
            LDAP_CACHE_LOCK();
950
951
            the_compare_node.dn = (char *)dn;
952
            the_compare_node.attrib = (char *)"objectClass";
953
            the_compare_node.value = (char *)sgc_ents[base_sgcIndex].name;
954
            the_compare_node.result = 0;
955
            the_compare_node.sgl_processed = 0;
956
            the_compare_node.subgroupList = NULL;
957
958
            compare_nodep = util_ald_cache_fetch(curl->compare_cache, &the_compare_node);
959
960
            if (compare_nodep == NULL) {
961
                /* Didn't find it. This shouldn't happen since we just called uldap_cache_compare. */
962
                LDAP_CACHE_UNLOCK();
963
                ldc->reason = "check_subgroups failed to find cached element.";
964
                return LDAP_COMPARE_FALSE;
965
            }
966
            else {
967
                /* Found the generic group entry... but the user isn't in this group or we wouldn't be here. */
968
                lcl_sgl_processedFlag = compare_nodep->sgl_processed;
969
                if(compare_nodep->sgl_processed && compare_nodep->subgroupList) {
970
                    /* Make a local copy of the subgroup list */
971
                    int i;
972
                    tmp_local_sgl = apr_pcalloc(r->pool, sizeof(util_compare_subgroup_t));
973
                    tmp_local_sgl->len = compare_nodep->subgroupList->len;
974
                    tmp_local_sgl->subgroupDNs = apr_pcalloc(r->pool, sizeof(char *) * compare_nodep->subgroupList->len);
975
                    for (i = 0; i < compare_nodep->subgroupList->len; i++) {
976
                        tmp_local_sgl->subgroupDNs[i] = apr_pstrdup(r->pool, compare_nodep->subgroupList->subgroupDNs[i]);
977
                    }
978
                }
979
            }
980
            /* unlock this read lock */
981
            LDAP_CACHE_UNLOCK();
982
        }
983
        else {
984
              /* If we get here, something is wrong. Caches should have been created and
985
                 this group entry should be found in the cache. */
986
            ldc->reason = "check_subgroups failed to find any caches.";
987
            return LDAP_COMPARE_FALSE;
988
        }
989
990
        result = LDAP_COMPARE_FALSE;
991
992
        /* No cache entry had a processed SGL. Retrieve from LDAP server */
993
        if ((lcl_sgl_processedFlag == 0) && (!tmp_local_sgl)) {
994
start_over:
995
            /* 3.B. The cache didn't have any subgrouplist yet. Go check for subgroups. */
996
            if (failures++ > 10) {
997
                /* too many failures */
998
                return result;
999
            }
1000
1001
            if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
1002
                /* connect failed */
1003
                return result;
1004
            }
1005
1006
            /* try to do the search */
1007
            result = ldap_search_ext_s(ldc->ldap, (char *)dn, LDAP_SCOPE_BASE,
1008
                                       (char *)"cn=*", subgroupAttrs, 0,
1009
                                       NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &sga_res);
1010
            if (result == LDAP_SERVER_DOWN) {
1011
                ldc->reason = "ldap_search_ext_s() for subgroups failed with server down";
1012
                uldap_connection_unbind(ldc);
1013
                goto start_over;
1014
            }
1015
1016
            /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
1017
            if (result != LDAP_SUCCESS) {
1018
                ldc->reason = "ldap_search_ext_s() for subgroups failed";
1019
                return result;
1020
            }
1021
1022
            entry = ldap_first_entry(ldc->ldap, sga_res);
1023
1024
            /*
1025
             * Get values for the provided sub-group attributes.
1026
             */
1027
            if (subgroupAttrs) {
1028
                int indx = 0, tmp_sgcIndex;
1029
1030
                while (subgroupAttrs[indx]) {
1031
                    char **values;
1032
                    int val_index = 0;
1033
1034
                    /* Get *all* matching "member" values from this group. */
1035
                    values = ldap_get_values(ldc->ldap, entry, subgroupAttrs[indx]);
1036
1037
                    if (values) {
1038
                        val_index = 0;
1039
                        /*
1040
                         * Now we are going to pare the subgroup members of this group to *just*
1041
                         * the subgroups, add them to the compare_nodep, and then proceed to check
1042
                         * the new level of subgroups.
1043
                         */
1044
                        while (values[val_index]) {
1045
                            /* Check if this entry really is a group. */
1046
                            tmp_sgcIndex = 0;
1047
                            result = LDAP_COMPARE_FALSE;
1048
                            while ((tmp_sgcIndex < subgroupclasses->nelts) && (result != LDAP_COMPARE_TRUE)) {
1049
                                result = uldap_cache_compare(r, ldc, url, values[val_index], "objectClass",
1050
                                                             sgc_ents[tmp_sgcIndex].name);
1051
1052
                                if (result != LDAP_COMPARE_TRUE) {
1053
                                    tmp_sgcIndex++;
1054
                                }
1055
                            }
1056
                            /* It's a group, so add it to the array.  */
1057
                            if (result == LDAP_COMPARE_TRUE) {
1058
                                char **newgrp = (char **) apr_array_push(subgroups);
1059
                                *newgrp = apr_pstrdup(r->pool, values[val_index]);
1060
                            }
1061
                            val_index++;
1062
                        }
1063
                        ldap_value_free(values);
1064
                    }
1065
                    indx++;
1066
                }
1067
            }
1068
1069
            ldap_msgfree(sga_res);
1070
1071
            if (subgroups->nelts > 0) {
1072
                /* We need to fill in tmp_local_subgroups using the data from LDAP */
1073
                int sgindex;
1074
                char **group;
1075
                tmp_local_sgl = apr_pcalloc(r->pool, sizeof(util_compare_subgroup_t));
1076
                tmp_local_sgl->subgroupDNs  = apr_pcalloc(r->pool, sizeof(char *) * (subgroups->nelts));
1077
                for (sgindex = 0; (group = apr_array_pop(subgroups)); sgindex++) {
1078
                    tmp_local_sgl->subgroupDNs[sgindex] = apr_pstrdup(r->pool, *group);
1079
                }
1080
                tmp_local_sgl->len = sgindex;
1081
            }
1082
1083
            /* Find the generic group cache entry and add the sgl. */
1084
            LDAP_CACHE_LOCK();
1085
1086
            the_compare_node.dn = (char *)dn;
1087
            the_compare_node.attrib = (char *)"objectClass";
1088
            the_compare_node.value = (char *)sgc_ents[base_sgcIndex].name;
1089
            the_compare_node.result = 0;
1090
            the_compare_node.sgl_processed = 0;
1091
            the_compare_node.subgroupList = NULL;
1092
1093
            compare_nodep = util_ald_cache_fetch(curl->compare_cache, &the_compare_node);
1094
1095
            if (compare_nodep == NULL) {
1096
                /* Didn't find it. This shouldn't happen since we just called uldap_cache_compare. */
1097
                LDAP_CACHE_UNLOCK();
1098
                ldc->reason = "check_subgroups failed to find the cache entry to add sub-group list to.";
1099
                return LDAP_COMPARE_FALSE;
1100
            }
1101
            else {
1102
                 /* overwrite SGL if it was previously updated between the last
1103
                 ** two times we looked at the cache
1104
                 */
1105
                 compare_nodep->sgl_processed = 1;
1106
                 if (tmp_local_sgl) {
1107
                     compare_nodep->subgroupList = util_ald_sgl_dup(curl->compare_cache, tmp_local_sgl);
1108
                 }
1109
                 else {
1110
                     /* We didn't find a single subgroup, next time save us from looking */
1111
                     compare_nodep->subgroupList = NULL;
1112
                 }
1113
            }
1114
            /* unlock this read lock */
1115
            LDAP_CACHE_UNLOCK();
1116
        }
1117
1118
        /* tmp_local_sgl has either been created, or copied out of the cache */
1119
        /* If tmp_local_sgl is NULL, there are no subgroups to process and we'll return false */
1120
        result = LDAP_COMPARE_FALSE;
1121
        if (tmp_local_sgl) {
1122
            int sgindex = 0;
1123
            const char *group = NULL;
1124
            while ((result != LDAP_COMPARE_TRUE) && (sgindex < tmp_local_sgl->len)) {
1125
                group = tmp_local_sgl->subgroupDNs[sgindex];
1126
                /* 4. Now loop through the subgroupList and call uldap_cache_compare to check for the user. */
1127
                result = uldap_cache_compare(r, ldc, url, group, attrib, value);
1128
                if (result == LDAP_COMPARE_TRUE) {
1129
                    /* 4.A. We found the user in the subgroup. Return LDAP_COMPARE_TRUE. */
1130
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "[%" APR_PID_T_FMT "] util_ldap:"
1131
                                  " Found the user in a subgroup (%s) at level %d of %d. (7).",
1132
                                  getpid(), group, cur_subgroup_depth+1, max_subgroup_depth);
1133
                }
1134
                else {
1135
                    /* 4.B. We didn't find the user in this subgroup, so recurse into it and keep looking. */
1136
                    result = uldap_cache_check_subgroups(r, ldc, url, group, attrib,
1137
                                                         value, subgroupAttrs, subgroupclasses,
1138
                                                         cur_subgroup_depth+1, max_subgroup_depth);
1139
                }
1140
                sgindex++;
1141
            }
1142
        }
1143
    }
1144
1145
    return result;
1146
}
1147
1148
852
static int uldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc,
1149
static int uldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc,
853
                                   const char *url, const char *basedn,
1150
                                   const char *url, const char *basedn,
854
                                   int scope, char **attrs, const char *filter,
1151
                                   int scope, char **attrs, const char *filter,
Lines 2106-2111 Link Here
2106
    APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);
2403
    APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);
2107
    APR_REGISTER_OPTIONAL_FN(uldap_cache_getuserdn);
2404
    APR_REGISTER_OPTIONAL_FN(uldap_cache_getuserdn);
2108
    APR_REGISTER_OPTIONAL_FN(uldap_ssl_supported);
2405
    APR_REGISTER_OPTIONAL_FN(uldap_ssl_supported);
2406
    APR_REGISTER_OPTIONAL_FN(uldap_cache_check_subgroups);
2109
2407
2110
    ap_hook_post_config(util_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
2408
    ap_hook_post_config(util_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
2111
    ap_hook_handler(util_ldap_handler, NULL, NULL, APR_HOOK_MIDDLE);
2409
    ap_hook_handler(util_ldap_handler, NULL, NULL, APR_HOOK_MIDDLE);
(-)httpd-trunk/modules/aaa/mod_authnz_ldap.c (-11 / +146 lines)
Lines 67-75 Link Here
67
67
68
    int have_ldap_url;              /* Set if we have found an LDAP url */
68
    int have_ldap_url;              /* Set if we have found an LDAP url */
69
69
70
    apr_array_header_t *groupattr;  /* List of Group attributes */
70
    apr_array_header_t *groupattr;  /* List of Group attributes identifying user members. Default:"member uniqueMember" */
71
    int group_attrib_is_dn;         /* If true, the group attribute is the DN, otherwise,
71
    int group_attrib_is_dn;         /* If true, the group attribute is the DN, otherwise,
72
                                        it's the exact string passed by the HTTP client */
72
                                        it's the exact string passed by the HTTP client */
73
    apr_array_header_t *subgroupattrs; /* List of attributes used to find subgroup references
74
                                          within a group directory entry. Default:"member uniqueMember" */
75
    char **sgAttributes;            /* Array of strings constructed (post-config) from subgroupattrs. Last entry is NULL. */
76
    apr_array_header_t *subgroupclasses; /* List of object classes of sub-groups. Default:"groupOfNames groupOfUniqueNames" */
77
    int maxNestingDepth;            /* Maximum recursive nesting depth permitted during subgroup processing. Default: 10 */
73
78
74
    int secure;                     /* True if SSL connections are requested */
79
    int secure;                     /* True if SSL connections are requested */
75
} authn_ldap_config_t;
80
} authn_ldap_config_t;
Lines 82-97 Link Here
82
/* maximum group elements supported */
87
/* maximum group elements supported */
83
#define GROUPATTR_MAX_ELTS 10
88
#define GROUPATTR_MAX_ELTS 10
84
89
85
struct mod_auth_ldap_groupattr_entry_t {
86
    char *name;
87
};
88
89
module AP_MODULE_DECLARE_DATA authnz_ldap_module;
90
module AP_MODULE_DECLARE_DATA authnz_ldap_module;
90
91
91
static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
92
static APR_OPTIONAL_FN_TYPE(uldap_connection_close) *util_ldap_connection_close;
92
static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
93
static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
93
static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
94
static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
94
static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
95
static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
96
static APR_OPTIONAL_FN_TYPE(uldap_cache_check_subgroups) *util_ldap_cache_check_subgroups;
95
static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
97
static APR_OPTIONAL_FN_TYPE(uldap_cache_checkuserid) *util_ldap_cache_checkuserid;
96
static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
98
static APR_OPTIONAL_FN_TYPE(uldap_cache_getuserdn) *util_ldap_cache_getuserdn;
97
static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
99
static APR_OPTIONAL_FN_TYPE(uldap_ssl_supported) *util_ldap_ssl_supported;
Lines 285-290 Link Here
285
*/
287
*/
286
    sec->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS,
288
    sec->groupattr = apr_array_make(p, GROUPATTR_MAX_ELTS,
287
                                    sizeof(struct mod_auth_ldap_groupattr_entry_t));
289
                                    sizeof(struct mod_auth_ldap_groupattr_entry_t));
290
    sec->subgroupattrs = apr_array_make(p, GROUPATTR_MAX_ELTS,
291
                                    sizeof(struct mod_auth_ldap_groupattr_entry_t));
292
    sec->subgroupclasses = apr_array_make(p, GROUPATTR_MAX_ELTS,
293
                                    sizeof(struct mod_auth_ldap_groupattr_entry_t));
288
294
289
    sec->have_ldap_url = 0;
295
    sec->have_ldap_url = 0;
290
    sec->url = "";
296
    sec->url = "";
Lines 294-299 Link Here
294
    sec->deref = always;
300
    sec->deref = always;
295
    sec->group_attrib_is_dn = 1;
301
    sec->group_attrib_is_dn = 1;
296
    sec->secure = -1;   /*Initialize to unset*/
302
    sec->secure = -1;   /*Initialize to unset*/
303
    sec->maxNestingDepth = 10;
304
    sec->sgAttributes = NULL;
297
305
298
    sec->user_is_dn = 0;
306
    sec->user_is_dn = 0;
299
    sec->remote_user_attribute = NULL;
307
    sec->remote_user_attribute = NULL;
Lines 648-660 Link Here
648
        grp = apr_array_push(sec->groupattr);
656
        grp = apr_array_push(sec->groupattr);
649
        grp->name = "member";
657
        grp->name = "member";
650
        grp = apr_array_push(sec->groupattr);
658
        grp = apr_array_push(sec->groupattr);
651
        grp->name = "uniquemember";
659
        grp->name = "uniqueMember";
652
#if APR_HAS_THREADS
660
#if APR_HAS_THREADS
653
        apr_thread_mutex_unlock(sec->lock);
661
        apr_thread_mutex_unlock(sec->lock);
654
#endif
662
#endif
655
    }
663
    }
656
664
657
    /*
665
    /*
666
     * If there are no elements in the sub group attribute array, the default
667
     * should be member and uniquemember; populate the array now.
668
     */
669
    if (sec->subgroupattrs->nelts == 0) {
670
        struct mod_auth_ldap_groupattr_entry_t *grp;
671
#if APR_HAS_THREADS
672
        apr_thread_mutex_lock(sec->lock);
673
#endif
674
        grp = apr_array_push(sec->subgroupattrs);
675
        grp->name = "member";
676
        grp = apr_array_push(sec->subgroupattrs);
677
        grp->name = "uniqueMember";
678
#if APR_HAS_THREADS
679
        apr_thread_mutex_unlock(sec->lock);
680
#endif
681
    }
682
683
    /*
684
     * If there are no elements in the sub group classes array, the default
685
     * should be groupOfNames and groupOfUniqueNames; populate the array now.
686
     */
687
    if (sec->subgroupclasses->nelts == 0) {
688
        struct mod_auth_ldap_groupattr_entry_t *grp;
689
#if APR_HAS_THREADS
690
        apr_thread_mutex_lock(sec->lock);
691
#endif
692
        grp = apr_array_push(sec->subgroupclasses);
693
        grp->name = "groupOfNames";
694
        grp = apr_array_push(sec->subgroupclasses);
695
        grp->name = "groupOfUniqueNames";
696
#if APR_HAS_THREADS
697
        apr_thread_mutex_unlock(sec->lock);
698
#endif
699
    }
700
701
    /*
658
     * If we have been authenticated by some other module than mod_auth_ldap,
702
     * If we have been authenticated by some other module than mod_auth_ldap,
659
     * the req structure needed for authorization needs to be created
703
     * the req structure needed for authorization needs to be created
660
     * and populated with the userid and DN of the account in LDAP
704
     * and populated with the userid and DN of the account in LDAP
Lines 734-739 Link Here
734
                              getpid(), ent[i].name, ldc->reason, ldap_err2string(result));
778
                              getpid(), ent[i].name, ldc->reason, ldap_err2string(result));
735
                return AUTHZ_GRANTED;
779
                return AUTHZ_GRANTED;
736
            }
780
            }
781
            case LDAP_COMPARE_FALSE: {
782
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
783
                               "[%" APR_PID_T_FMT "] auth_ldap authorise: require group \"%s\": "
784
                               "failed [%s][%d - %s], checking sub-groups",
785
                               getpid(), t, ldc->reason, result, ldap_err2string(result));
786
787
                if(sec->sgAttributes == NULL) {
788
                    struct mod_auth_ldap_groupattr_entry_t *sg_ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->subgroupattrs->elts;
789
                    char **sg_attrs;
790
                    int sga_index;
791
792
                    /* Allocate a null-terminated array of attribute strings. */
793
                    sg_attrs = apr_pcalloc(sec->pool, (sec->subgroupattrs->nelts+1) * sizeof(char *));
794
                    for(sga_index = 0; sga_index < sec->subgroupattrs->nelts; sga_index++) {
795
                        sg_attrs[sga_index] = apr_pstrdup(sec->pool, sg_ent[sga_index].name);
796
                    }
797
                    sg_attrs[sec->subgroupattrs->nelts] = NULL;
798
                    sec->sgAttributes = sg_attrs;
799
                }
800
801
                result = util_ldap_cache_check_subgroups(r, ldc, sec->url, t, ent[i].name,
802
                                                         sec->group_attrib_is_dn ? req->dn : req->user,
803
                                                         sec->sgAttributes, sec->subgroupclasses,
804
                                                         0, sec->maxNestingDepth);
805
                if(result == LDAP_COMPARE_TRUE) {
806
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
807
                                   "[%" APR_PID_T_FMT "] auth_ldap authorise: require group (sub-group): "
808
                                   "authorisation successful (attribute %s) [%s][%d - %s]",
809
                                   getpid(), ent[i].name, ldc->reason, result, ldap_err2string(result));
810
                     return OK;
811
                }
812
                else {
813
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
814
                                   "[%" APR_PID_T_FMT "] auth_ldap authorise: require group (sub-group) \"%s\": "
815
                                   "authorisation failed [%s][%d - %s]",
816
                                   getpid(), t, ldc->reason, result, ldap_err2string(result));
817
                }
818
                break;
819
            }
737
            default: {
820
            default: {
738
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
821
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
739
                              "[%" APR_PID_T_FMT "] auth_ldap authorize: require group \"%s\": "
822
                              "[%" APR_PID_T_FMT "] auth_ldap authorize: require group \"%s\": "
Lines 1249-1254 Link Here
1249
    return NULL;
1332
    return NULL;
1250
}
1333
}
1251
1334
1335
static const char *mod_auth_ldap_add_subgroup_attribute(cmd_parms *cmd, void *config, const char *arg)
1336
{
1337
    struct mod_auth_ldap_groupattr_entry_t *new;
1338
1339
    authn_ldap_config_t *sec = config;
1340
1341
    if (sec->subgroupattrs->nelts > GROUPATTR_MAX_ELTS)
1342
        return "Too many AuthLDAPSubGroupAttribute values";
1343
1344
    new = apr_array_push(sec->subgroupattrs);
1345
    new->name = apr_pstrdup(cmd->pool, arg);
1346
1347
    return NULL;
1348
}
1349
1350
static const char *mod_auth_ldap_add_subgroup_class(cmd_parms *cmd, void *config, const char *arg)
1351
{
1352
    struct mod_auth_ldap_groupattr_entry_t *new;
1353
1354
    authn_ldap_config_t *sec = config;
1355
1356
    if (sec->subgroupclasses->nelts > GROUPATTR_MAX_ELTS)
1357
        return "Too many AuthLDAPSubGroupClass values";
1358
1359
    new = apr_array_push(sec->subgroupclasses);
1360
    new->name = apr_pstrdup(cmd->pool, arg);
1361
1362
    return NULL;
1363
}
1364
1365
static const char *mod_auth_ldap_set_subgroup_maxdepth(cmd_parms *cmd,
1366
                                                       void *config,
1367
                                                       const char *max_depth)
1368
{
1369
    authn_ldap_config_t *sec = config;
1370
1371
    sec->maxNestingDepth = atol(max_depth);
1372
1373
    return NULL;
1374
}
1375
1252
static const char *mod_auth_ldap_add_group_attribute(cmd_parms *cmd, void *config, const char *arg)
1376
static const char *mod_auth_ldap_add_group_attribute(cmd_parms *cmd, void *config, const char *arg)
1253
{
1377
{
1254
    struct mod_auth_ldap_groupattr_entry_t *new;
1378
    struct mod_auth_ldap_groupattr_entry_t *new;
Lines 1312-1319 Link Here
1312
                 "the REMOTE_USER variable will contain whatever value the remote user sent."),
1436
                 "the REMOTE_USER variable will contain whatever value the remote user sent."),
1313
1437
1314
    AP_INIT_TAKE1("AuthLDAPRemoteUserAttribute", ap_set_string_slot,
1438
    AP_INIT_TAKE1("AuthLDAPRemoteUserAttribute", ap_set_string_slot,
1315
                 (void *)APR_OFFSETOF(authn_ldap_config_t, 
1439
                 (void *)APR_OFFSETOF(authn_ldap_config_t, remote_user_attribute), OR_AUTHCFG,
1316
                                      remote_user_attribute), OR_AUTHCFG,
1317
                 "Override the user supplied username and place the "
1440
                 "Override the user supplied username and place the "
1318
                 "contents of this attribute in the REMOTE_USER "
1441
                 "contents of this attribute in the REMOTE_USER "
1319
                 "environment variable."),
1442
                 "environment variable."),
Lines 1325-1333 Link Here
1325
                 "(at the expense of possible false matches). See the documentation for "
1448
                 "(at the expense of possible false matches). See the documentation for "
1326
                 "a complete description of this option."),
1449
                 "a complete description of this option."),
1327
1450
1451
    AP_INIT_ITERATE("AuthLDAPSubGroupAttribute", mod_auth_ldap_add_subgroup_attribute, NULL, OR_AUTHCFG,
1452
                    "Attribute labels used to define sub-group (or nested group) membership in groups - "
1453
                    "defaults to member and uniqueMember (one per directive)"),
1454
1455
    AP_INIT_ITERATE("AuthLDAPSubGroupClass", mod_auth_ldap_add_subgroup_class, NULL, OR_AUTHCFG,
1456
                     "LDAP objectClass values used to identify sub-group instances - "
1457
                     "defaults to groupOfNames and groupOfUniqueNames (one per directive)"),
1458
1459
    AP_INIT_TAKE1("AuthLDAPMaxSubGroupDepth", mod_auth_ldap_set_subgroup_maxdepth, NULL, OR_AUTHCFG,
1460
                      "Maximum subgroup nesting depth to be evaluated - defaults to 10 (top-level group = 0)"),
1461
1328
    AP_INIT_ITERATE("AuthLDAPGroupAttribute", mod_auth_ldap_add_group_attribute, NULL, OR_AUTHCFG,
1462
    AP_INIT_ITERATE("AuthLDAPGroupAttribute", mod_auth_ldap_add_group_attribute, NULL, OR_AUTHCFG,
1329
                    "A list of attributes used to define group membership - defaults to "
1463
                    "A list of attribute labels used to identify the user members of groups - defaults to "
1330
                    "member and uniquemember"),
1464
                    "member and uniquemember (one per directive)"),
1331
1465
1332
    AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot,
1466
    AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot,
1333
                 (void *)APR_OFFSETOF(authn_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG,
1467
                 (void *)APR_OFFSETOF(authn_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG,
Lines 1336-1342 Link Here
1336
                 "provided by the client directly. Defaults to 'on'."),
1470
                 "provided by the client directly. Defaults to 'on'."),
1337
1471
1338
    AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG,
1472
    AP_INIT_TAKE1("AuthLDAPDereferenceAliases", mod_auth_ldap_set_deref, NULL, OR_AUTHCFG,
1339
                  "Determines how aliases are handled during a search. Can bo one of the"
1473
                  "Determines how aliases are handled during a search. Can be one of the"
1340
                  "values \"never\", \"searching\", \"finding\", or \"always\". "
1474
                  "values \"never\", \"searching\", \"finding\", or \"always\". "
1341
                  "Defaults to always."),
1475
                  "Defaults to always."),
1342
1476
Lines 1468-1473 Link Here
1468
    util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
1602
    util_ldap_cache_checkuserid = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
1469
    util_ldap_cache_getuserdn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
1603
    util_ldap_cache_getuserdn   = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
1470
    util_ldap_ssl_supported     = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
1604
    util_ldap_ssl_supported     = APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
1605
    util_ldap_cache_check_subgroups = APR_RETRIEVE_OPTIONAL_FN(uldap_cache_check_subgroups);
1471
}
1606
}
1472
1607
1473
static void register_hooks(apr_pool_t *p)
1608
static void register_hooks(apr_pool_t *p)
(-)httpd-trunk/include/util_ldap.h (-1 / +36 lines)
Lines 144-149 Link Here
144
144
145
} util_ldap_state_t;
145
} util_ldap_state_t;
146
146
147
/* Used to store arrays of attribute labels/values. */
148
struct mod_auth_ldap_groupattr_entry_t {
149
    char *name;
150
};
147
151
148
/**
152
/**
149
 * Open a connection to an LDAP server
153
 * Open a connection to an LDAP server
Lines 244-250 Link Here
244
 * @param attrib The attribute within the object we are comparing for.
248
 * @param attrib The attribute within the object we are comparing for.
245
 * @param value The value of the attribute we are trying to compare for. 
249
 * @param value The value of the attribute we are trying to compare for. 
246
 * @tip Use this function to determine whether an attribute/value pair exists within an
250
 * @tip Use this function to determine whether an attribute/value pair exists within an
247
 *      object. Typically this would be used to determine LDAP group membership.
251
 *      object. Typically this would be used to determine LDAP top-level group
252
 *      membership.
248
 * @fn int util_ldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
253
 * @fn int util_ldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
249
 *                                      const char *url, const char *dn, const char *attrib, const char *value)
254
 *                                      const char *url, const char *dn, const char *attrib, const char *value)
250
 */
255
 */
Lines 252-257 Link Here
252
                            const char *url, const char *dn, const char *attrib, const char *value));
257
                            const char *url, const char *dn, const char *attrib, const char *value));
253
258
254
/**
259
/**
260
 * An LDAP function that checks if the specified user is a member of a subgroup.
261
 * @param r The request record
262
 * @param ldc The LDAP connection being used.
263
 * @param url The URL of the LDAP connection - used for deciding which cache to use.
264
 * @param dn The DN of the object in which we find subgroups to search within.
265
 * @param attrib The attribute within group objects that identify users.
266
 * @param value The user attribute value we are trying to compare for.
267
 * @param subgroupAttrs The attributes within group objects that identify subgroups.
268
 *                      Array of strings.
269
 * @param subgroupclasses The objectClass values used to identify groups (and
270
 *                      subgroups). apr_array_header_t *.
271
 * @param cur_subgroup_depth Current recursive depth during subgroup processing.
272
 * @param max_subgroup_depth Maximum depth of recursion allowed during subgroup
273
 *                           processing.
274
 * @tip Use this function to determine whether an attribute/value pair exists within a
275
 *      starting group object or one of its nested subgroups. Typically this would be
276
 *      used to determine LDAP nested group membership.
277
 * @deffunc int util_ldap_cache_check_subgroups(request_rec *r, util_ldap_connection_t
278
 *                                      *ldc, const char *url, const char *dn,
279
 *                                      const char *attrib, const char value,
280
 *                                      char **subgroupAttrs, apr_array_header_t
281
 *                                      *subgroupclasses, int cur_subgroup_depth, int
282
 *                                      max_subgroup_depth )
283
 */
284
APR_DECLARE_OPTIONAL_FN(int,uldap_cache_check_subgroups,(request_rec *r, util_ldap_connection_t *ldc,
285
                                       const char *url, const char *dn, const char *attrib, const char *value,
286
                                       char **subgroupAttrs, apr_array_header_t *subgroupclasses,
287
                                       int cur_subgroup_depth, int max_subgroup_depth));
288
289
/**
255
 * Checks a username/password combination by binding to the LDAP server
290
 * Checks a username/password combination by binding to the LDAP server
256
 * @param r The request record
291
 * @param r The request record
257
 * @param ldc The LDAP connection being used.
292
 * @param ldc The LDAP connection being used.

Return to bug 42891