1 /*
2 * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * Copyright (c) 1993 Regents of the University of Michigan.
10 * All rights reserved.
11 *
12 * getfilter.c -- optional add-on to libldap
13 */
14
15 #ifndef lint
16 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
17 #endif
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #if defined(NeXT)
23 #include <regex.h>
24 #endif
25 #ifdef MACOS
26 #include <stdlib.h>
27 #include "macos.h"
28 #else /* MACOS */
29 #ifdef DOS
30 #include <malloc.h>
31 #include "msdos.h"
32 #else /* DOS */
33 #include <sys/types.h>
34 #include <sys/file.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #ifndef VMS
38 #include <unistd.h>
39 #endif /* VMS */
40 #endif /* DOS */
41 #endif /* MACOS */
42
43 #include "lber.h"
44 #include "ldap.h"
45 #include "ldap-private.h"
46 #include "ldap-int.h"
47 #include "regex.h"
48
49 #ifdef NEEDPROTOS
50 static int break_into_words( char *str, char *delims, char ***wordsp );
51 int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp );
52 void free_strarray( char **sap );
53 #else /* NEEDPROTOS */
54 static int break_into_words();
55 int next_line_tokens();
56 void free_strarray();
57 #endif /* NEEDPROTOS */
58
59 #if !defined( MACOS ) && !defined( DOS )
60 extern int errno;
61 extern char *re_comp();
62 #endif
63
64 #define FILT_MAX_LINE_LEN 1024
65
66 LDAPFiltDesc *
ldap_init_getfilter(char * fname)67 ldap_init_getfilter( char *fname )
68 {
69 FILE *fp;
70 char *buf;
71 ssize_t rlen, len;
72 int eof;
73 LDAPFiltDesc *lfdp;
74
75 if (( fp = fopen( fname, "r" )) == NULL ) {
76 return( NULL );
77 }
78
79 if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */
80 fclose( fp );
81 return( NULL );
82 }
83
84 len = ftell( fp );
85
86 if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */
87 fclose( fp );
88 return( NULL );
89 }
90
91 if (( buf = malloc( len )) == NULL ) {
92 fclose( fp );
93 return( NULL );
94 }
95
96 rlen = fread( buf, (size_t) 1, len, fp );
97 eof = feof( fp );
98 fclose( fp );
99
100 if ( rlen != len && !eof ) { /* error: didn't get the whole file */
101 free( buf );
102 return( NULL );
103 }
104
105
106 lfdp = ldap_init_getfilter_buf( buf, rlen );
107 free( buf );
108
109 return( lfdp );
110 }
111
112
113 LDAPFiltDesc *
ldap_init_getfilter_buf(char * buf,ssize_t buflen)114 ldap_init_getfilter_buf( char *buf, ssize_t buflen )
115 {
116 LDAPFiltDesc *lfdp;
117 LDAPFiltList *flp, *nextflp;
118 LDAPFiltInfo *fip, *nextfip;
119 char *tag, **tok;
120 int tokcnt, i;
121
122 if (( lfdp = (LDAPFiltDesc *)calloc( (size_t) 1, sizeof( LDAPFiltDesc))) == NULL ) {
123 return( NULL );
124 }
125
126 flp = nextflp = NULL;
127 fip = NULL;
128 tag = NULL;
129
130 while ( buflen > 0 && ( tokcnt = next_line_tokens( &buf, &buflen, &tok ))
131 > 0 ) {
132
133 switch( tokcnt ) {
134 case 1: /* tag line */
135 if ( tag != NULL ) {
136 free( tag );
137 }
138 tag = tok[ 0 ];
139 free( tok );
140 break;
141 case 4:
142 case 5: /* start of filter info. list */
143 if (( nextflp = (LDAPFiltList *)calloc( (size_t) 1, sizeof( LDAPFiltList )))
144 == NULL ) {
145 ldap_getfilter_free( lfdp );
146 return( NULL );
147 }
148 nextflp->lfl_tag = strdup( tag );
149 nextflp->lfl_pattern = tok[ 0 ];
150 if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
151 #ifndef NO_USERINTERFACE
152 ldap_getfilter_free( lfdp );
153 fprintf( stderr, "bad regular expresssion %s\n",
154 nextflp->lfl_pattern );
155 #if !defined( MACOS ) && !defined( DOS )
156 errno = EINVAL;
157 #endif
158 #endif /* NO_USERINTERFACE */
159 free_strarray( tok );
160 return( NULL );
161 }
162
163 nextflp->lfl_delims = tok[ 1 ];
164 nextflp->lfl_ilist = NULL;
165 nextflp->lfl_next = NULL;
166 if ( flp == NULL ) { /* first one */
167 lfdp->lfd_filtlist = nextflp;
168 } else {
169 flp->lfl_next = nextflp;
170 }
171 flp = nextflp;
172 fip = NULL;
173 for ( i = 2; i < 5; ++i ) {
174 tok[ i - 2 ] = tok[ i ];
175 }
176 /* fall through */
177
178 case 2:
179 case 3: /* filter, desc, and optional search scope */
180 if ( nextflp != NULL ) { /* add to info list */
181 if (( nextfip = (LDAPFiltInfo *)calloc( (size_t) 1,
182 sizeof( LDAPFiltInfo ))) == NULL ) {
183 ldap_getfilter_free( lfdp );
184 free_strarray( tok );
185 return( NULL );
186 }
187 if ( fip == NULL ) { /* first one */
188 nextflp->lfl_ilist = nextfip;
189 } else {
190 fip->lfi_next = nextfip;
191 }
192 fip = nextfip;
193 nextfip->lfi_next = NULL;
194 nextfip->lfi_filter = tok[ 0 ];
195 nextfip->lfi_desc = tok[ 1 ];
196 if ( tok[ 2 ] != NULL ) {
197 if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
198 nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
199 } else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
200 nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
201 } else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
202 nextfip->lfi_scope = LDAP_SCOPE_BASE;
203 } else {
204 free_strarray( tok );
205 ldap_getfilter_free( lfdp );
206 #if !defined( MACOS ) && !defined( DOS )
207 errno = EINVAL;
208 #endif
209 return( NULL );
210 }
211 free( tok[ 2 ] );
212 tok[ 2 ] = NULL;
213 } else {
214 nextfip->lfi_scope = LDAP_SCOPE_SUBTREE; /* default */
215 }
216 nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
217 strchr( tok[ 0 ], '~' ) == NULL );
218 free( tok );
219 }
220 break;
221
222 default:
223 free_strarray( tok );
224 ldap_getfilter_free( lfdp );
225 #if !defined( MACOS ) && !defined( DOS )
226 errno = EINVAL;
227 #endif
228 return( NULL );
229 }
230 }
231
232 if ( tag != NULL ) {
233 free( tag );
234 }
235
236 return( lfdp );
237 }
238
239
240 void
ldap_setfilteraffixes(LDAPFiltDesc * lfdp,char * prefix,char * suffix)241 ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
242 {
243 if ( lfdp->lfd_filtprefix != NULL ) {
244 free( lfdp->lfd_filtprefix );
245 }
246 lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : strdup( prefix );
247
248 if ( lfdp->lfd_filtsuffix != NULL ) {
249 free( lfdp->lfd_filtsuffix );
250 }
251 lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : strdup( suffix );
252 }
253
254
255 LDAPFiltInfo *
ldap_getfirstfilter(LDAPFiltDesc * lfdp,char * tagpat,char * value)256 ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
257 {
258 LDAPFiltList *flp;
259
260 if ( lfdp->lfd_curvalcopy != NULL ) {
261 free( lfdp->lfd_curvalcopy );
262 free( lfdp->lfd_curvalwords );
263 }
264
265 lfdp->lfd_curval = value;
266 lfdp->lfd_curfip = NULL;
267
268 for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
269 if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
270 && re_comp( flp->lfl_pattern ) == NULL
271 && re_exec( lfdp->lfd_curval ) == 1 ) {
272 lfdp->lfd_curfip = flp->lfl_ilist;
273 break;
274 }
275 }
276
277 if ( lfdp->lfd_curfip == NULL ) {
278 return( NULL );
279 }
280
281 if (( lfdp->lfd_curvalcopy = strdup( value )) == NULL ) {
282 return( NULL );
283 }
284
285 if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
286 &lfdp->lfd_curvalwords ) < 0 ) {
287 free( lfdp->lfd_curvalcopy );
288 lfdp->lfd_curvalcopy = NULL;
289 return( NULL );
290 }
291
292 return( ldap_getnextfilter( lfdp ));
293 }
294
295
296 LDAPFiltInfo *
ldap_getnextfilter(LDAPFiltDesc * lfdp)297 ldap_getnextfilter( LDAPFiltDesc *lfdp )
298 {
299 LDAPFiltInfo *fip;
300
301 fip = lfdp->lfd_curfip;
302
303 if ( fip == NULL ) {
304 return( NULL );
305 }
306
307 lfdp->lfd_curfip = fip->lfi_next;
308
309 ldap_build_filter( lfdp->lfd_filter, (size_t) LDAP_FILT_MAXSIZ, fip->lfi_filter,
310 lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
311 lfdp->lfd_curval, lfdp->lfd_curvalwords );
312 lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
313 lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
314 lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
315 lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
316
317 return( &lfdp->lfd_retfi );
318 }
319
320
321 void
ldap_build_filter(char * filtbuf,size_t buflen,char * pattern,char * prefix,char * suffix,char * attr,char * value,char ** valwords)322 ldap_build_filter( char *filtbuf, size_t buflen, char *pattern,
323 char *prefix, char *suffix, char *attr, char *value, char **valwords )
324 {
325 char *p, *f;
326 size_t slen;
327 int i, wordcount, wordnum, endwordnum;
328
329 if ( valwords == NULL ) {
330 wordcount = 0;
331 } else {
332 for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
333 ;
334 }
335 }
336
337 f = filtbuf;
338
339 if ( prefix != NULL ) {
340 strcpy( f, prefix );
341 f += strlen( prefix );
342 }
343
344 for ( p = pattern; *p != '\0'; ++p ) {
345 if ( *p == '%' ) {
346 ++p;
347 if ( *p == 'v' ) {
348 if ( isdigit( *(p+1))) {
349 ++p;
350 wordnum = *p - '1';
351 if ( *(p+1) == '-' ) {
352 ++p;
353 if ( isdigit( *(p+1))) {
354 ++p;
355 endwordnum = *p - '1'; /* e.g., "%v2-4" */
356 #ifndef SUN /* Patch from innosoft Craig.Watkins 08.Jul.97 */
357 if ( endwordnum > wordcount - 1 ) {
358 endwordnum = wordcount - 1;
359 }
360 #endif
361 } else {
362 endwordnum = wordcount - 1; /* e.g., "%v2-" */
363 }
364 } else {
365 endwordnum = wordnum; /* e.g., "%v2" */
366 }
367 #ifdef SUN /* Patch from innosoft Craig.Watkins 08.Jul.97 */
368 if ( endwordnum > wordcount - 1 ) {
369 endwordnum = wordcount - 1;
370 }
371 #endif
372 if ( wordcount > 0 ) {
373 for ( i = wordnum; i <= endwordnum; ++i ) {
374 if ( i > wordnum ) { /* add blank btw words */
375 *f++ = ' ';
376 }
377 slen = strlen( valwords[ i ] );
378 SAFEMEMCPY( f, valwords[ i ], slen );
379 f += slen;
380 }
381 }
382 } else if ( *(p+1) == '$' ) {
383 ++p;
384 if ( wordcount > 0 ) {
385 wordnum = wordcount - 1;
386 slen = strlen( valwords[ wordnum ] );
387 SAFEMEMCPY( f, valwords[ wordnum ], slen );
388 f += slen;
389 }
390 } else if ( value != NULL ) {
391 slen = strlen( value );
392 SAFEMEMCPY( f, value, slen );
393 f += slen;
394 }
395 } else if ( *p == 'a' && attr != NULL ) {
396 slen = strlen( attr );
397 SAFEMEMCPY( f, attr, slen );
398 f += slen;
399 } else {
400 *f++ = *p;
401 }
402 } else {
403 *f++ = *p;
404 }
405
406 if ( f - filtbuf > buflen ) {
407 /* sanity check */
408 --f;
409 break;
410 }
411 }
412
413 if ( suffix != NULL && ( f - filtbuf ) < buflen ) {
414 strcpy( f, suffix );
415 } else {
416 *f = '\0';
417 }
418 }
419
420
421 static int
break_into_words(char * str,char * delims,char *** wordsp)422 break_into_words( char *str, char *delims, char ***wordsp )
423 {
424 char *word, **words;
425 int count;
426
427 if (( words = (char **)calloc( (size_t) 1, sizeof( char * ))) == NULL ) {
428 return( -1 );
429 }
430 count = 0;
431 words[ count ] = NULL;
432
433 word = strtok( str, delims );
434 while ( word != NULL ) {
435 if (( words = (char **)realloc( words,
436 ( count + 2 ) * sizeof( char * ))) == NULL ) {
437 return( -1 );
438 }
439
440 words[ count ] = word;
441 words[ ++count ] = NULL;
442 word = strtok( NULL, delims );
443 }
444
445 *wordsp = words;
446 return( count );
447 }
448