]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/alias.c
Import minor trace output cleanup
[openldap] / servers / slapd / back-ldbm / alias.c
1 /*
2  * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to ITSD, Government of BC. The name of ITSD
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <ac/socket.h>          /* Get struct sockaddr for slap.h */
18 #include "slap.h"
19 #include "back-ldbm.h"
20 #include "proto-back-ldbm.h"
21
22 /*
23  * given an alias object, dereference it to its end point.
24  * entry returned has reader lock 
25  */
26 Entry *derefAlias_r ( Backend     *be,
27                     Connection  *conn,
28                     Operation   *op,
29                     Entry       *e)
30 {
31   Attribute *a;
32   int       depth;
33   char      **pastAliases;
34   char      *matched;
35
36   Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
37
38   /*
39    * try to deref fully, up to a maximum depth.  If the max depth exceeded
40    * then send an error
41    */
42   for ( depth = 0;
43         ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
44           ( depth < be->be_maxDerefDepth );
45         ++depth) 
46   {
47
48     /* 
49      * make sure there is a defined aliasedobjectname.  
50      * can only have one value so just use first value (0) in the attr list. 
51      */     
52     if (a->a_vals[0] && a->a_vals[0]->bv_val) {
53       char *newDN, *oldDN;
54
55       Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n", 
56              e->e_dn, a->a_vals[0]->bv_val, 0 );
57       newDN = ch_strdup (a->a_vals[0]->bv_val);
58       oldDN = ch_strdup (e->e_dn);
59
60       /*
61        * ok, so what happens if there is an alias in the DN of a dereferenced
62        * alias object?  
63        */
64       if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) {
65
66         /* could not deref return error  */
67         Debug( LDAP_DEBUG_TRACE, 
68                "<= %s is a dangling alias to %s\n", 
69                oldDN, newDN, 0 );
70         send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
71                           "Dangling Alias" );
72
73                         if(matched != NULL) free(matched);
74       }
75       free (newDN);
76       free (oldDN);
77     }
78     else {
79       /*
80        * there was an aliasedobjectname defined but no data.
81        * this can't happen, right?
82        */
83         Debug( LDAP_DEBUG_TRACE, 
84                "<= %s has no data in aliasedobjectname attribute\n", 
85                e->e_dn, 0, 0 );
86         send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
87                           "Alias missing aliasedobjectname" );
88     }
89   }
90
91   /*
92    * warn if we pulled out due to exceeding the maximum deref depth
93    */
94   if ( depth >= be->be_maxDerefDepth ) {
95     Debug( LDAP_DEBUG_TRACE, 
96            "<= %s exceeded maximum deref depth %d\n", 
97            e->e_dn, be->be_maxDerefDepth, 0 );
98     send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
99                         "Maximum alias dereference depth exceeded" );
100   }
101
102   return e;
103 }
104
105 /*
106  * given a DN fully deref it and return the real DN or original DN if it fails
107  */
108 char *derefDN ( Backend     *be,
109                 Connection  *conn,
110                 Operation   *op,
111                 char        *dn
112 )
113 {
114   struct ldbminfo *li = (struct ldbminfo *) be->be_private;
115   char  *matched = 0;
116   char  *newDN = NULL;
117   int   depth, i;
118   Entry         *eMatched;
119   Entry         *eDeref;
120   Entry         *eNew;
121   
122
123   Debug( LDAP_DEBUG_TRACE, 
124          "<= dereferencing dn: \"%s\"\n", 
125          dn, 0, 0 );
126   
127   newDN = ch_strdup ( dn );
128
129   /* while we don't have a matched dn, deref the DN */
130   for ( depth = 0;
131         ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) &&
132           (depth < be->be_maxDerefDepth);
133         ++depth ) {
134     
135     if ((matched != NULL) && *matched) {        
136       char *submatch;
137       
138       /* 
139        * make sure there actually is an entry for the matched part 
140        */
141       if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) {
142         char  *remainder; /* part before the aliased part */
143         int  rlen = strlen(newDN) - strlen(matched);
144         
145         Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
146         
147         remainder = ch_malloc (rlen + 1);
148         strncpy ( remainder, newDN, rlen );
149         remainder[rlen] = '\0';
150         
151         Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
152         
153         if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) {
154           free (matched);
155           matched = NULL;
156           free (newDN);
157           newDN = NULL;
158           free (remainder);
159           remainder = NULL;
160           break; /*  no associated entry, dont deref */
161         }
162         else {
163
164           Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
165
166           i = strcasecmp (matched, eNew->e_dn);
167           /* free reader lock */
168           cache_return_entry_r(&li->li_cache, eNew);
169           if (! i) {
170             /* newDN same as old so not an alias, no need to go further */
171             free (newDN);
172             newDN = NULL;
173             free (matched);
174             matched = NULL;
175             free (remainder);
176             break;
177           }
178
179           /* 
180            * we have dereferenced the aliased part so put
181            * the new dn together
182            */
183           free (newDN);
184           newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
185           strcpy (newDN, remainder);
186           strcat (newDN, eMatched->e_dn);
187           Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
188
189           free (matched);
190           matched = NULL;
191           free (remainder);
192         }
193         /* free reader lock */
194         cache_return_entry_r(&li->li_cache, eMatched);
195       }
196       else {
197         if(submatch != NULL) free(submatch);
198         break; /* there was no entry for the matched part */
199       }
200     }
201     else {
202       break; /* there was no matched part */
203     }
204   }
205   
206   if(eMatched != NULL) {
207     /* free reader lock */
208     cache_return_entry_r(&li->li_cache, eMatched);
209   }
210
211   /*
212    * the final part of the DN might be an alias 
213    * so try to dereference it.
214    */
215   if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) {
216     if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) {
217       free (newDN);
218       newDN = ch_strdup (eDeref->e_dn);
219       /* free reader lock */
220       cache_return_entry_r(&li->li_cache, eDeref);
221     }
222     /* free reader lock */
223     cache_return_entry_r(&li->li_cache, eNew);
224   }
225   
226   /*
227    * warn if we exceeded the max depth as the resulting DN may not be dereferenced
228    */
229   if (depth >= be->be_maxDerefDepth) {
230     Debug( LDAP_DEBUG_TRACE, 
231            "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n", 
232            dn, newDN, 0 );
233     send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
234                       "Maximum alias dereference depth exceeded for base" );
235   }
236
237   if (newDN == NULL) {
238     newDN = ch_strdup ( dn );
239   }
240   
241   Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 ); 
242   if (matched != NULL) free(matched);
243
244   return newDN;
245 }