]> git.sur5r.net Git - openldap/blob - servers/slapd/dn.c
Import minor dn related changes:
[openldap] / servers / slapd / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/ctype.h>
8 #include <ac/socket.h>
9 #include <ac/string.h>
10 #include <ac/time.h>
11
12 #include "slap.h"
13
14 #define B4TYPE          0
15 #define INTYPE          1
16 #define B4EQUAL         2
17 #define B4VALUE         3
18 #define INVALUE         4
19 #define INQUOTEDVALUE   5
20 #define B4SEPARATOR     6
21
22 /*
23  * dn_normalize - put dn into a canonical format.  the dn is
24  * normalized in place, as well as returned.
25  */
26
27 char *
28 dn_normalize( char *dn )
29 {
30         char    *d, *s;
31         int     state, gotesc;
32
33         /* Debug( LDAP_DEBUG_TRACE, "=> dn_normalize \"%s\"\n", dn, 0, 0 ); */
34
35         gotesc = 0;
36         state = B4TYPE;
37         for ( d = s = dn; *s; s++ ) {
38                 switch ( state ) {
39                 case B4TYPE:
40                         if ( ! SPACE( *s ) ) {
41                                 state = INTYPE;
42                                 *d++ = *s;
43                         }
44                         break;
45                 case INTYPE:
46                         if ( *s == '=' ) {
47                                 state = B4VALUE;
48                                 *d++ = *s;
49                         } else if ( SPACE( *s ) ) {
50                                 state = B4EQUAL;
51                         } else {
52                                 *d++ = *s;
53                         }
54                         break;
55                 case B4EQUAL:
56                         if ( *s == '=' ) {
57                                 state = B4VALUE;
58                                 *d++ = *s;
59                         } else if ( ! SPACE( *s ) ) {
60                                 /* not a valid dn - but what can we do here? */
61                                 *d++ = *s;
62                         }
63                         break;
64                 case B4VALUE:
65                         if ( *s == '"' ) {
66                                 state = INQUOTEDVALUE;
67                                 *d++ = *s;
68                         } else if ( ! SPACE( *s ) ) { 
69                                 state = INVALUE;
70                                 *d++ = *s;
71                         }
72                         break;
73                 case INVALUE:
74                         if ( !gotesc && SEPARATOR( *s ) ) {
75                                 while ( SPACE( *(d - 1) ) )
76                                         d--;
77                                 state = B4TYPE;
78                                 if ( *s == '+' ) {
79                                         *d++ = *s;
80                                 } else {
81                                         *d++ = ',';
82                                 }
83                         } else if ( gotesc && !NEEDSESCAPE( *s ) &&
84                             !SEPARATOR( *s ) ) {
85                                 *--d = *s;
86                                 d++;
87                         } else {
88                                 *d++ = *s;
89                         }
90                         break;
91                 case INQUOTEDVALUE:
92                         if ( !gotesc && *s == '"' ) {
93                                 state = B4SEPARATOR;
94                                 *d++ = *s;
95                         } else if ( gotesc && !NEEDSESCAPE( *s ) ) {
96                                 *--d = *s;
97                                 d++;
98                         } else {
99                                 *d++ = *s;
100                         }
101                         break;
102                 case B4SEPARATOR:
103                         if ( SEPARATOR( *s ) ) {
104                                 state = B4TYPE;
105                                 *d++ = *s;
106                         }
107                         break;
108                 default:
109                         Debug( LDAP_DEBUG_ANY,
110                             "dn_normalize - unknown state %d\n", state, 0, 0 );
111                         break;
112                 }
113                 if ( *s == '\\' ) {
114                         gotesc = 1;
115                 } else {
116                         gotesc = 0;
117                 }
118         }
119         *d = '\0';
120
121         /* Debug( LDAP_DEBUG_TRACE, "<= dn_normalize \"%s\"\n", dn, 0, 0 ); */
122         return( dn );
123 }
124
125 /*
126  * dn_normalize_case - put dn into a canonical form suitable for storing
127  * in a hash database.  this involves normalizing the case as well as
128  * the format.  the dn is normalized in place as well as returned.
129  */
130
131 char *
132 dn_normalize_case( char *dn )
133 {
134         char    *s;
135
136         /* normalize format */
137         dn_normalize( dn );
138
139         /* normalize case */
140         for ( s = dn; *s; s++ ) {
141                 *s = TOUPPER( *s );
142         }
143
144         return( dn );
145 }
146
147 /*
148  * dn_parent - return a copy of the dn of dn's parent
149  */
150
151 char *
152 dn_parent(
153     Backend     *be,
154     char        *dn
155 )
156 {
157         char    *s;
158         int     inquote, gotesc;
159
160         if( dn == NULL ) {
161                 return NULL;
162         }
163
164         while(*dn && SPACE(*dn)) {
165                 dn++;
166         }
167
168         if( *dn == '\0' ) {
169                 return( NULL );
170         }
171
172         if ( be_issuffix( be, dn ) ) {
173                 return( NULL );
174         }
175
176         /*
177          * no =, assume it is a dns name, like blah@some.domain.name
178          * if the blah@ part is there, return some.domain.name.  if
179          * it's just some.domain.name, return domain.name.
180          */
181         if ( strchr( dn, '=' ) == NULL ) {
182                 if ( (s = strchr( dn, '@' )) == NULL ) {
183                         if ( (s = strchr( dn, '.' )) == NULL ) {
184                                 return( NULL );
185                         }
186                 }
187                 if ( *(s + 1) == '\0' ) {
188                         return( NULL );
189                 } else {
190                         return( ch_strdup( &s[1] ) );
191                 }
192         }
193
194         /*
195          * else assume it is an X.500-style name, which looks like
196          * foo=bar,sha=baz,...
197          */
198
199         inquote = 0;
200         for ( s = dn; *s; s++ ) {
201                 if ( *s == '\\' ) {
202                         if ( *(s + 1) ) {
203                                 s++;
204                         }
205                         continue;
206                 }
207                 if ( inquote ) {
208                         if ( *s == '"' ) {
209                                 inquote = 0;
210                         }
211                 } else {
212                         if ( *s == '"' ) {
213                                 inquote = 1;
214                         } else if ( DNSEPARATOR( *s ) ) {
215                                 return( ch_strdup( &s[1] ) );
216                         }
217                 }
218         }
219
220         return( ch_strdup( "" ) );
221 }
222
223 /*
224  * dn_issuffix - tells whether suffix is a suffix of dn.  both dn
225  * and suffix must be normalized.
226  */
227
228 int
229 dn_issuffix(
230     char        *dn,
231     char        *suffix
232 )
233 {
234         int     dnlen, suffixlen;
235
236         if ( dn == NULL ) {
237                 return( 0 );
238         }
239
240         suffixlen = strlen( suffix );
241         dnlen = strlen( dn );
242
243         if ( suffixlen > dnlen ) {
244                 return( 0 );
245         }
246
247         return( strcmp( dn + dnlen - suffixlen, suffix ) == 0 );
248 }
249
250 /*
251  * dn_type - tells whether the given dn is an X.500 thing or DNS thing
252  * returns (defined in slap.h): DN_DNS          dns-style thing
253  *                              DN_X500         x500-style thing
254  */
255
256 int
257 dn_type( char *dn )
258 {
259         return( strchr( dn, '=' ) == NULL ? DN_DNS : DN_X500 );
260 }
261
262 char *
263 dn_upcase( char *dn )
264 {
265         char    *s;
266
267         /* normalize case */
268         for ( s = dn; *s; s++ ) {
269                 *s = TOUPPER( *s );
270         }
271
272         return( dn );
273 }