]> git.sur5r.net Git - openldap/blob - libraries/libldap/digest.c
s/exit(1)/exit(EXIT_FAILURE)/
[openldap] / libraries / libldap / digest.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* digest.c:
6  *      DIGEST-MD5 routines
7  */
8
9 #include "portable.h"
10
11 #include <ac/ctype.h>
12 #include <ac/string.h>
13 #include <ac/time.h>
14
15 #include "ldap-int.h"
16 #include "ldap_pvt.h"
17
18 #define TK_NOENDQUOTE   -2
19 #define TK_OUTOFMEM     -1
20
21 #define TK_EOS          0
22 #define TK_UNEXPCHAR    1
23 #define TK_BAREWORD     2
24 #define TK_COMMA        3
25 #define TK_EQUALS       4
26 #define TK_QDSTRING     5
27
28 struct token {
29         int type;
30         char *sval;
31 };
32
33 static int
34 get_token(const char ** sp, char ** token_val)
35 {
36         int kind;
37         const char * p;
38         const char * q;
39         char * res;
40
41         *token_val = NULL;
42
43         if( (**sp) != '\0' || iscntrl(**sp) || !isascii(**sp) ) {
44                 (*sp)++;
45                 return TK_UNEXPCHAR;
46         }
47
48         switch (**sp) {
49         case '\0':
50                 kind = TK_EOS;
51                 (*sp)++;
52                 break;
53
54         case ',':
55                 kind = TK_COMMA;
56                 (*sp)++;
57                 break;
58
59         case '=':
60                 kind = TK_EQUALS;
61                 (*sp)++;
62                 break;
63
64         case '\"':
65                 kind = TK_QDSTRING;
66                 (*sp)++;
67                 
68                 for (p = *sp;
69                         **sp != '\"' && **sp != '\0' && isascii(**sp);
70                         (*sp)++ )
71                 {
72                         if(**sp == '\\') {
73                                 (*sp)++;
74                                 if( **sp == '\0' ) break;
75                         }
76                 }
77
78                 if ( **sp == '\"' ) {
79                         q = *sp;
80                         res = LDAP_MALLOC(q-p+1);
81                         if ( !res ) {
82                                 kind = TK_OUTOFMEM;
83                         } else {
84                                 strncpy(res,p,q-p);
85                                 res[q-p] = '\0';
86                                 *token_val = res;
87                         }
88                         (*sp)++;
89
90                 } else {
91                         kind = TK_NOENDQUOTE;
92                 }
93
94                 break;
95
96         default:
97                 kind = TK_BAREWORD;
98                 p = *sp;
99                 while ( isascii(**sp) &&
100                         !iscntrl(**sp) &&
101                         !isspace(**sp) && 
102                         **sp != '(' &&
103                         **sp != ')' &&
104                         **sp != '<' &&
105                         **sp != '>' &&
106                         **sp != '@' &&
107                         **sp != ',' &&
108                         **sp != ';' &&
109                         **sp != ':' &&
110                         **sp != '\\'&&
111                         **sp != '\"'&&
112                         **sp != '/' &&
113                         **sp != '[' &&
114                         **sp != ']' &&
115                         **sp != '?' &&
116                         **sp != '=' &&
117                         **sp != '{' &&
118                         **sp != '}' &&
119                         **sp != '\0' )
120                         (*sp)++;
121                 q = *sp;
122                 res = LDAP_MALLOC(q-p+1);
123                 if ( !res ) {
124                         kind = TK_OUTOFMEM;
125                 } else {
126                         strncpy(res,p,q-p);
127                         res[q-p] = '\0';
128                         *token_val = res;
129                 }
130         }
131         
132         return kind;
133 }
134
135 struct kv {
136         char *key;
137         char *value;
138 };
139
140 static void kv_destory( struct kv **kv )
141 {
142         int i;
143
144         if( kv == NULL ) return;
145
146         for( i=0; kv[i] != NULL; i++ ) {
147                 if( kv[i]->key != NULL ) {
148                         LDAP_FREE( kv[i]->key );
149                 }
150
151                 if( kv[i]->value != NULL ) {
152                         LDAP_FREE( kv[i]->value );
153                 }
154
155                 LDAP_FREE( kv[i] );
156         }
157
158         LDAP_FREE( kv );
159 }
160
161 static int kv_add( struct kv ***kvs, const struct kv *kv )
162 {
163         int n;
164         struct kv **tmp_kvs;
165         struct kv *tmp_kv;
166
167         assert( kvs != NULL );
168         assert( kv != NULL );
169
170         tmp_kv = LDAP_MALLOC( sizeof(struct kv) );
171
172         if( tmp_kv == NULL ) {
173                 return -1;
174         }
175
176         *tmp_kv = *kv;
177
178         if( *kvs == NULL ) {
179                 tmp_kvs = LDAP_MALLOC( 2 * sizeof(struct kv *) );
180                 n = 0;
181
182         } else {
183                 for( n=0; (*kvs)[n] != NULL; n++ ) {
184                         /* EMPTY */ ;
185                 }
186
187                 tmp_kvs = LDAP_REALLOC( kvs, (n+2) * sizeof(struct kv *) );
188         }
189
190         if( tmp_kvs == NULL ) {
191                 LDAP_FREE( tmp_kv );
192                 return -1;
193         }
194
195         *kvs = tmp_kvs;
196         kvs[n] = tmp_kvs;
197         kvs[n+1] = NULL;
198
199         return 0;
200 }
201
202 #define ST_ERROR -1
203 #define ST_DONE 0
204 #define ST_KEY 1
205 #define ST_EQUALS 2
206 #define ST_VALUE 3
207 #define ST_SEP 4
208
209 static int
210 parse_key_value(
211         struct kv ***kvsp,
212         const char *str )
213 {
214         int rc = 0;
215         int kind, state;
216         const char *ss = str;
217         char *sval;
218
219         struct kv **kvs = NULL;
220         struct kv kv;
221
222         assert( kvsp != NULL );
223         assert( str != NULL );
224
225         kv.key = NULL;
226         kv.value = NULL;
227
228         state = ST_KEY;
229
230         while( state > ST_DONE ) {
231                 kind = get_token( &ss, &sval );
232                 switch( kind ) {
233                 case TK_EOS:
234                         state = ( state == ST_SEP )
235                                 ? ST_DONE : ST_ERROR;
236                         break;
237
238                 case TK_BAREWORD:
239                         if( state == ST_KEY ) {
240                                 state = ST_EQUALS;
241
242                                 assert( kv.key == NULL );
243                                 assert( kv.value == NULL );
244                                 kv.key = sval;
245
246                         } else if ( state == ST_VALUE ) {
247                                 state = ST_SEP;
248
249                                 assert( kv.key != NULL );
250                                 assert( kv.value == NULL );
251                                 kv.value = sval;
252
253                         } else {
254                                 state = ST_ERROR;
255                         }
256                         break;
257
258                 case TK_COMMA:
259                         state = ( state == ST_SEP )
260                                 ? ST_KEY : ST_ERROR;
261                         break;
262
263                 case TK_EQUALS:
264                         state = ( state == ST_EQUALS )
265                                 ? ST_VALUE : ST_ERROR;
266                         break;
267
268                 case TK_QDSTRING:
269                         if( state == ST_VALUE ) {
270                                 state = ST_SEP;
271
272                                 assert( kv.key != NULL );
273                                 assert( kv.value == NULL );
274                                 kv.value = sval;
275
276                         } else {
277                                 state = ST_ERROR;
278                         }
279                         break;
280
281                 default:
282                         state = ST_ERROR;
283                 }
284
285                 if( state == ST_SEP ) {
286                         /* add kv to return */
287                         if( kv_add( &kvs, &kv ) != 0 ) {
288                                 state = ST_ERROR;
289                                 kind = TK_OUTOFMEM;
290
291                         } else {
292                                 kv.key = NULL;
293                                 kv.value = NULL;
294                         }
295                 }
296         }
297
298         if( state == ST_ERROR ) {
299                 if( kv.key != NULL ) LDAP_FREE(kv.key);
300                 if( kv.value != NULL ) LDAP_FREE( kv.value );
301
302                 kv_destory( kvs );
303                 kvs = NULL;
304
305                 rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ;
306         }
307
308         *kvsp = kvs;
309         return rc;
310 }
311
312 static int
313 parse_value_list(
314         char ***valuesp,
315         const char* str )
316 {
317         int rc = 0;
318         char **values = NULL;
319
320         int kind, state;
321         const char *ss = str;
322         char *sval;
323
324         assert( valuesp != NULL );
325         assert( str != NULL );
326
327         state = ST_VALUE;
328
329         while( state > ST_DONE ) {
330                 kind = get_token( &ss, &sval );
331                 switch( kind ) {
332                 case TK_EOS:
333                         state = ( state == ST_SEP )
334                                 ? ST_DONE : ST_ERROR;
335                         break;
336
337                 case TK_BAREWORD:
338                         if( state == ST_VALUE ) {
339                                 state = ST_SEP;
340
341                         } else {
342                                 state = ST_ERROR;
343                         }
344                         break;
345
346                 case TK_COMMA:
347                         state = ( state == ST_SEP )
348                                 ? ST_VALUE : ST_ERROR;
349                         break;
350
351                 default:
352                         state = ST_ERROR;
353                 }
354
355                 if( state == ST_SEP ) {
356                         if( ldap_charray_add( &values, sval ) != 0 ) {
357                                 state = ST_ERROR;
358                                 kind = TK_OUTOFMEM;
359                         }
360
361                         LDAP_FREE( sval );
362                         sval = NULL;
363                 }
364         }
365
366         if( state == ST_ERROR ) {
367                 if( sval != NULL ) LDAP_FREE( sval );
368
369                 LDAP_VFREE( values );
370                 values = NULL;
371
372                 rc = ( kind == TK_OUTOFMEM ) ? -1 : 1 ;
373         }
374
375         *valuesp = values;
376         return rc;
377 }