]> git.sur5r.net Git - openldap/blob - servers/slapd/shell-backends/shellutil.c
Happy New Year
[openldap] / servers / slapd / shell-backends / shellutil.c
1 /* shellutil.c - common routines useful when building shell-based backends */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2018 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor. The name of the University
22  * may not be used to endorse or promote products derived from this
23  * software without specific prior written permission. This software
24  * is provided ``as is'' without express or implied warranty.
25  */
26 /* ACKNOWLEDGEMENTS:
27  * This work was originally developed by the University of Michigan
28  * (as part of U-MICH LDAP).
29  */
30
31
32 #include "portable.h"
33
34 #include <stdio.h>
35
36 #include <ac/stdlib.h>
37 #include <ac/stdarg.h>
38
39 #include <pwd.h>
40
41 #include <ac/ctype.h>
42 #include <ac/string.h>
43
44 #include <lber.h>
45 #include <ldap.h>
46 #include "shellutil.h"
47
48
49 int     debugflg;
50 char    *progname;
51
52 static struct inputparams       ips[] = {
53     IP_TYPE_SUFFIX,     "suffix",
54     IP_TYPE_BASE,       "base",
55     IP_TYPE_SCOPE,      "scope",
56     IP_TYPE_ALIASDEREF, "deref",
57     IP_TYPE_SIZELIMIT,  "sizelimit",
58     IP_TYPE_TIMELIMIT,  "timelimit",
59     IP_TYPE_FILTER,     "filter",
60     IP_TYPE_ATTRS,      "attrs",
61     IP_TYPE_ATTRSONLY,  "attrsonly",
62     0,                  NULL
63 };
64
65
66 void
67 write_result( FILE *fp, int code, char *matched, char *info )
68 {
69     fprintf( fp, "RESULT\ncode: %d\n", code );
70     debug_printf( ">> RESULT\n" );
71     debug_printf( ">> code: %d\n", code );
72
73     if ( matched != NULL ) {
74         fprintf( fp, "matched: %s\n", matched );
75         debug_printf( ">> matched: %s\n", matched );
76     }
77
78     if ( info != NULL ) {
79         fprintf( fp, "info: %s\n", info );
80         debug_printf( ">> info: %s\n", info );
81     }
82 }
83
84
85 void
86 write_entry( struct ldop *op, struct ldentry *entry, FILE *ofp )
87 {
88     struct ldattr       **app;
89     char                **valp;
90
91     fprintf( ofp, "dn: %s\n", entry->lde_dn );
92     for ( app = entry->lde_attrs; *app != NULL; ++app ) {
93         if ( attr_requested( (*app)->lda_name, op )) {
94             for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) {
95                 fprintf( ofp, "%s: %s\n", (*app)->lda_name, *valp );
96             }
97         }
98     }
99     fputc( '\n', ofp );
100 }
101
102
103 int
104 test_filter( struct ldop *op, struct ldentry *entry )
105 {
106     return ((random() & 0x07 ) == 0x07) /* XXX random for now */
107                 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
108 }
109
110
111 int
112 attr_requested( char *name, struct ldop *op )
113 {
114     char        **ap;
115
116     if ( op->ldop_srch.ldsp_attrs == NULL ) {   /* special case */
117         return( 1 );
118     }
119
120     for ( ap = op->ldop_srch.ldsp_attrs; *ap != NULL; ++ap ) {
121         if ( strcasecmp( name, *ap ) == 0 ) {
122             return( 1 );
123         }
124     }
125
126     return( 0 );
127 }
128
129
130 void
131 free_entry( struct ldentry *entry )
132 {
133     struct ldattr       **app;
134     char                **valp;
135
136     free( entry->lde_dn );
137
138     for ( app = entry->lde_attrs; *app != NULL; ++app ) {
139         for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) {
140             free( *valp );
141         }
142         free( (*app)->lda_values );
143         free( (*app)->lda_name );
144     }
145
146     free( entry->lde_attrs );
147     free( entry );
148 }
149
150
151 int
152 parse_input( FILE *ifp, FILE *ofp, struct ldop *op )
153 {
154     char                *p, *args, line[ MAXLINELEN + 1 ];
155     struct inputparams  *ip;
156
157     if ( fgets( line, MAXLINELEN, ifp ) == NULL ) {
158         write_result( ofp, LDAP_OTHER, NULL, "Empty Input" );
159     }
160     line[ strlen( line ) - 1 ] = '\0';
161     if ( strncasecmp( line, STR_OP_SEARCH, sizeof( STR_OP_SEARCH ) - 1 )
162             != 0 ) {
163         write_result( ofp, LDAP_UNWILLING_TO_PERFORM, NULL,
164                 "Operation Not Supported" );
165         return( -1 );
166     }
167
168     op->ldop_op = LDOP_SEARCH;
169
170     while ( fgets( line, MAXLINELEN, ifp ) != NULL ) {
171         line[ strlen( line ) - 1 ] = '\0';
172         debug_printf( "<< %s\n", line );
173
174         args = line;
175         if (( ip = find_input_tag( &args )) == NULL ) {
176             debug_printf( "ignoring %s\n", line );
177             continue;
178         }
179
180         switch( ip->ip_type ) {
181         case IP_TYPE_SUFFIX:
182             add_strval( &op->ldop_suffixes, args );
183             break;
184         case IP_TYPE_BASE:
185             op->ldop_dn = estrdup( args );
186             break;
187         case IP_TYPE_SCOPE:
188             if ( lutil_atoi( &op->ldop_srch.ldsp_scope, args ) != 0 ||
189                 ( op->ldop_srch.ldsp_scope != LDAP_SCOPE_BASE &&
190                     op->ldop_srch.ldsp_scope != LDAP_SCOPE_ONELEVEL &&
191                     op->ldop_srch.ldsp_scope != LDAP_SCOPE_SUBTREE ) )
192             {
193                 write_result( ofp, LDAP_OTHER, NULL, "Bad scope" );
194                 return( -1 );
195             }
196             break;
197         case IP_TYPE_ALIASDEREF:
198             if ( lutil_atoi( &op->ldop_srch.ldsp_aliasderef, args ) != 0 ) {
199                 write_result( ofp, LDAP_OTHER, NULL, "Bad alias deref" );
200                 return( -1 );
201             }
202             break;
203         case IP_TYPE_SIZELIMIT:
204             if ( lutil_atoi( &op->ldop_srch.ldsp_sizelimit, args ) != 0 ) {
205                 write_result( ofp, LDAP_OTHER, NULL, "Bad size limit" );
206                 return( -1 );
207             }
208             break;
209         case IP_TYPE_TIMELIMIT:
210             if ( lutil_atoi( &op->ldop_srch.ldsp_timelimit, args ) != 0 ) {
211                 write_result( ofp, LDAP_OTHER, NULL, "Bad time limit" );
212                 return( -1 );
213             }
214             break;
215         case IP_TYPE_FILTER:
216             op->ldop_srch.ldsp_filter = estrdup( args );
217             break;
218         case IP_TYPE_ATTRSONLY:
219             op->ldop_srch.ldsp_attrsonly = ( *args != '0' );
220             break;
221         case IP_TYPE_ATTRS:
222             if ( strcmp( args, "all" ) == 0 ) {
223                 op->ldop_srch.ldsp_attrs = NULL;
224             } else {
225                 while ( args != NULL ) {
226                     if (( p = strchr( args, ' ' )) != NULL ) {
227                         *p++ = '\0';
228                         while ( isspace( (unsigned char) *p )) {
229                             ++p;
230                         }
231                     }
232                     add_strval( &op->ldop_srch.ldsp_attrs, args );
233                     args = p;
234                 }
235             }
236             break;
237         }
238     }
239
240     if ( op->ldop_suffixes == NULL || op->ldop_dn == NULL ||
241                 op->ldop_srch.ldsp_filter == NULL ) {
242         write_result( ofp, LDAP_OTHER, NULL,
243                 "Required suffix:, base:, or filter: missing" );
244         return( -1 );
245     }
246
247     return( 0 );
248 }
249
250
251 struct inputparams *
252 find_input_tag( char **linep )  /* linep is set to start of args */
253 {
254     int         i;
255     char        *p;
256
257     if (( p = strchr( *linep, ':' )) == NULL || p == *linep ) {
258         return( NULL );
259     }
260
261     for ( i = 0; ips[ i ].ip_type != 0; ++i ) {
262         if ( strncasecmp( *linep, ips[ i ].ip_tag, p - *linep ) == 0 ) {
263             while ( isspace( (unsigned char) *(++p) )) {
264                 ;
265             }
266             *linep = p;
267             return( &ips[ i ] );
268         }
269     }
270
271     return( NULL );
272 }
273
274
275 void
276 add_strval( char ***sp, char *val )
277 {
278     int         i;
279     char        **vallist;
280
281     vallist = *sp;
282
283     if ( vallist == NULL ) {
284         i = 0;
285     } else {
286         for ( i = 0; vallist[ i ] != NULL; ++i ) {
287             ;
288         }
289     }
290
291     vallist = (char **)erealloc( vallist, ( i + 2 ) * sizeof( char * ));
292     vallist[ i ] = estrdup( val );
293     vallist[ ++i ] = NULL;
294     *sp = vallist;
295 }
296
297
298 char *
299 estrdup( char *s )
300 {
301     char        *p;
302
303     if (( p = strdup( s )) == NULL ) {
304         debug_printf( "strdup failed\n" );
305         exit( EXIT_FAILURE );
306     }
307
308     return( p );
309 }
310
311
312 void *
313 erealloc( void *s, unsigned size )
314 {
315     char        *p;
316
317     if ( s == NULL ) {
318         p = malloc( size );
319     } else {
320         p = realloc( s, size );
321     }
322
323     if ( p == NULL ) {
324         debug_printf( "realloc( p, %d ) failed\n", size );
325         exit( EXIT_FAILURE );
326     }
327
328     return( p );
329 }
330
331
332 char *
333 ecalloc( unsigned nelem, unsigned elsize )
334 {
335     char        *p;
336
337     if (( p = calloc( nelem, elsize )) == NULL ) {
338         debug_printf( "calloc( %d, %d ) failed\n", nelem, elsize );
339         exit( EXIT_FAILURE );
340     }
341
342     return( p );
343 }
344
345
346 #ifdef LDAP_DEBUG
347
348 /* VARARGS */
349 void
350 debug_printf( const char *fmt, ... )
351 {
352     va_list     ap;
353
354         if ( debugflg ) {
355                 va_start( ap, fmt );
356                 fprintf( stderr, "%s: ", progname );
357                 vfprintf( stderr, fmt, ap );
358                 va_end( ap );
359         }
360 }
361
362
363 void
364 dump_ldop( struct ldop *op )
365 {
366     if ( !debugflg ) {
367         return;
368     }
369
370     debug_printf( "SEARCH operation\n" );
371     if ( op->ldop_suffixes == NULL ) {
372         debug_printf( "    suffix: NONE\n" );
373     } else {
374         int     i;
375         for ( i = 0; op->ldop_suffixes[ i ] != NULL; ++i ) {
376             debug_printf( "    suffix: <%s>\n", op->ldop_suffixes[ i ] );
377         }
378     }
379     debug_printf( "        dn: <%s>\n", op->ldop_dn );
380     debug_printf( "     scope: <%d>\n", op->ldop_srch.ldsp_scope );
381     debug_printf( "    filter: <%s>\n", op->ldop_srch.ldsp_filter );
382     debug_printf( "aliasderef: <%d>\n", op->ldop_srch.ldsp_aliasderef );
383     debug_printf( " sizelimit: <%d>\n", op->ldop_srch.ldsp_sizelimit );
384     debug_printf( " timelimit: <%d>\n", op->ldop_srch.ldsp_timelimit );
385     debug_printf( " attrsonly: <%d>\n", op->ldop_srch.ldsp_attrsonly );
386     if ( op->ldop_srch.ldsp_attrs == NULL ) {
387         debug_printf( "     attrs: ALL\n" );
388     } else {
389         int     i;
390
391         for ( i = 0; op->ldop_srch.ldsp_attrs[ i ] != NULL; ++i ) {
392             debug_printf( "  attrs: <%s>\n", op->ldop_srch.ldsp_attrs[ i ] );
393         }
394     }
395 }
396 #endif /* LDAP_DEBUG */