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