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