xref: /onnv-gate/usr/src/lib/libldap4/common/getfilter.c (revision 0:68f95e015346)
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