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-2011 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 49int debugflg; 50char *progname; 51 52static 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 66void 67write_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 85void 86write_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 103int 104test_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 111int 112attr_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 130void 131free_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 151int 152parse_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 251struct inputparams * 252find_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 275void 276add_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 298char * 299estrdup( 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 312void * 313erealloc( 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 332char * 333ecalloc( 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 */ 349void 350debug_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 363void 364dump_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 */ 397