]> git.sur5r.net Git - openldap/blob - libraries/libldap/dn.c
Add support for useronly configuration attributes.
[openldap] / libraries / libldap / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "ldap-int.h"
18
19 #if 0
20 /* this should wait for UTF-8 routines */
21
22 #define B4LEADTYPE              0
23 #define B4TYPE                  1
24 #define INOIDTYPE               2
25 #define INKEYTYPE               3
26 #define B4EQUAL                 4
27 #define B4VALUE                 5
28 #define INVALUE                 6
29 #define INQUOTEDVALUE   7
30 #define B4SEPARATOR             8
31
32 /*
33  * ldap_dn_normalize - put dn into a canonical format
34  * and return it.
35  */
36
37 char *
38 ldap_dn_normalize( const char *dn )
39 {
40         char    *d, *s;
41         int     state, gotesc;
42         char *ndn;
43
44         if( dn == NULL ) {
45                 return NULL;
46         }
47
48         ndn = LDAP_STRDUP( dn );
49
50         if( ndn == NULL ) {
51                 return NULL;
52         }
53
54         gotesc = 0;
55         state = B4LEADTYPE;
56         for ( d = s = ndn; *s; s++ ) {
57                 switch ( state ) {
58                 case B4LEADTYPE:
59                 case B4TYPE:
60                         if ( LDAP_LEADOIDCHAR(*s) ) {
61                                 state = INOIDTYPE;
62                                 *d++ = *s;
63                         } else if ( LDAP_LEADKEYCHAR(*s) ) {
64                                 state = INKEYTYPE;
65                                 *d++ = *s;
66                         } else if ( ! LDAP_SPACE( *s ) ) {
67                                 dn = NULL;
68                                 state = INKEYTYPE;
69                                 *d++ = *s;
70                         }
71                         break;
72
73                 case INOIDTYPE:
74                         if ( LDAP_OIDCHAR(*s) ) {
75                                 *d++ = *s;
76                         } else if ( *s == '=' ) {
77                                 state = B4VALUE;
78                                 *d++ = *s;
79                         } else if ( LDAP_SPACE( *s ) ) {
80                                 state = B4EQUAL;
81                         } else {
82                                 dn = NULL;
83                                 *d++ = *s;
84                         }
85                         break;
86
87                 case INKEYTYPE:
88                         if ( LDAP_KEYCHAR(*s) ) {
89                                 *d++ = *s;
90                         } else if ( *s == '=' ) {
91                                 state = B4VALUE;
92                                 *d++ = *s;
93                         } else if ( LDAP_SPACE( *s ) ) {
94                                 state = B4EQUAL;
95                         } else {
96                                 dn = NULL;
97                                 *d++ = *s;
98                         }
99                         break;
100
101                 case B4EQUAL:
102                         if ( *s == '=' ) {
103                                 state = B4VALUE;
104                                 *d++ = *s;
105                         } else if ( ! LDAP_SPACE( *s ) ) {
106                                 /* not a valid dn - but what can we do here? */
107                                 *d++ = *s;
108                                 dn = NULL;
109                         }
110                         break;
111
112                 case B4VALUE:
113                         if ( *s == '"' ) {
114                                 state = INQUOTEDVALUE;
115                                 *d++ = *s;
116                         } else if ( ! LDAP_SPACE( *s ) ) { 
117                                 state = INVALUE;
118                                 *d++ = *s;
119                         }
120                         break;
121
122                 case INVALUE:
123                         if ( !gotesc && LDAP_SEPARATOR( *s ) ) {
124                                 while ( LDAP_SPACE( *(d - 1) ) )
125                                         d--;
126                                 state = B4TYPE;
127                                 if ( *s == '+' ) {
128                                         *d++ = *s;
129                                 } else {
130                                         *d++ = ',';
131                                 }
132                         } else if ( gotesc && !LDAP_NEEDSESCAPE( *s ) &&
133                             !LDAP_SEPARATOR( *s ) ) {
134                                 *--d = *s;
135                                 d++;
136                         } else {
137                                 *d++ = *s;
138                         }
139                         break;
140
141                 case INQUOTEDVALUE:
142                         if ( !gotesc && *s == '"' ) {
143                                 state = B4SEPARATOR;
144                                 *d++ = *s;
145                         } else if ( gotesc && !LDAP_NEEDSESCAPE( *s ) ) {
146                                 *--d = *s;
147                                 d++;
148                         } else {
149                                 *d++ = *s;
150                         }
151                         break;
152                 case B4SEPARATOR:
153                         if ( LDAP_SEPARATOR( *s ) ) {
154                                 state = B4TYPE;
155                                 *d++ = *s;
156                         }
157                         break;
158                 default:
159                         dn = NULL;
160                         Debug( LDAP_DEBUG_ANY,
161                             "dn_normalize - unknown state %d\n", state, 0, 0 );
162                         break;
163                 }
164                 if ( *s == '\\' ) {
165                         gotesc = 1;
166                 } else {
167                         gotesc = 0;
168                 }
169         }
170         *d = '\0';
171
172         if( gotesc ) {
173                 /* shouldn't be left in escape */
174                 dn = NULL;
175         }
176
177         /* check end state */
178         switch( state ) {
179         case B4LEADTYPE:        /* looking for first type */
180         case B4SEPARATOR:       /* looking for separator */
181         case INVALUE:           /* inside value */
182                 break;
183         default:
184                 dn = NULL;
185         }
186
187         if( dn == NULL ) {
188                 return( ndn );
189                 ndn = NULL;
190         }
191
192         return( ndn );
193 }
194
195 /*
196  * ldap_dn_parent - return a copy of the dn of dn's parent
197  */
198
199 char *
200 ldap_dn_parent(
201     const char *dn
202 )
203 {
204         const char      *s;
205         int     inquote;
206
207         if( dn == NULL ) {
208                 return NULL;
209         }
210
211         while(*dn && LDAP_SPACE(*dn)) {
212                 dn++;
213         }
214
215         if( *dn == '\0' ) {
216                 return( NULL );
217         }
218
219         /*
220          * no =, assume it is a dns name, like blah@some.domain.name
221          * if the blah@ part is there, return some.domain.name.  if
222          * it's just some.domain.name, return domain.name.
223          */
224         if ( strchr( dn, '=' ) == NULL ) {
225                 if ( (s = strchr( dn, '@' )) == NULL ) {
226                         if ( (s = strchr( dn, '.' )) == NULL ) {
227                                 return( NULL );
228                         }
229                 }
230                 if ( *(s + 1) == '\0' ) {
231                         return( NULL );
232                 } else {
233                         return( LDAP_STRDUP( &s[1] ) );
234                 }
235         }
236
237         /*
238          * else assume it is an X.500-style name, which looks like
239          * foo=bar,sha=baz,...
240          */
241
242         inquote = 0;
243         for ( s = dn; *s; s++ ) {
244                 if ( *s == '\\' ) {
245                         if ( *(s + 1) ) {
246                                 s++;
247                         }
248                         continue;
249                 }
250                 if ( inquote ) {
251                         if ( *s == '"' ) {
252                                 inquote = 0;
253                         }
254                 } else {
255                         if ( *s == '"' ) {
256                                 inquote = 1;
257                         } else if ( LDAP_DNSEPARATOR( *s ) ) {
258                                 return( LDAP_STRDUP( &s[1] ) );
259                         }
260                 }
261         }
262
263         return( LDAP_STRDUP( "" ) );
264 }
265
266 char * ldap_dn_rdn( 
267     const char  *dn )
268 {
269         char    *s;
270         char    *rdn;
271         int     inquote;
272
273         if( dn == NULL ) {
274                 return NULL;
275         }
276
277         while(*dn && LDAP_SPACE(*dn)) {
278                 dn++;
279         }
280
281         if( *dn == '\0' ) {
282                 return( NULL );
283         }
284
285         rdn = LDAP_STRDUP( dn );
286
287         if( rdn == NULL ) {
288                 return NULL;
289         }
290
291 #ifdef DNS_DN
292         /*
293          * no =, assume it is a dns name, like blah@some.domain.name
294          * if the blah@ part is there, return some.domain.name.  if
295          * it's just some.domain.name, return domain.name.
296          */
297         if ( strchr( rdn, '=' ) == NULL ) {
298                 if ( (s = strchr( rdn, '@' )) == NULL ) {
299                         if ( (s = strchr( rdn, '.' )) == NULL ) {
300                                 return( rdn );
301                         }
302                 }
303                 *s = '\0';
304                 return( rdn );
305         }
306 #endif
307
308         /*
309          * else assume it is an X.500-style name, which looks like
310          * foo=bar,sha=baz,...
311          */
312
313         inquote = 0;
314
315         for ( s = rdn; *s; s++ ) {
316                 if ( *s == '\\' ) {
317                         if ( *(s + 1) ) {
318                                 s++;
319                         }
320                         continue;
321                 }
322                 if ( inquote ) {
323                         if ( *s == '"' ) {
324                                 inquote = 0;
325                         }
326                 } else {
327                         if ( *s == '"' ) {
328                                 inquote = 1;
329                         } else if ( LDAP_DNSEPARATOR( *s ) ) {
330                                 *s = '\0';
331                                 return( rdn );
332                         }
333                 }
334         }
335
336         return( rdn );
337 }
338
339 #endif