1 /* $OpenLDAP: pkg/ldap/libraries/libldap/test.c,v 1.55.2.3 2008/02/11 23:26:41 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2008 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/stdlib.h>
23 #include <ac/socket.h>
24 #include <ac/string.h>
26 #include <ac/unistd.h>
30 #ifdef HAVE_SYS_FILE_H
39 /* including the "internal" defs is legit and nec. since this test routine has
40 * a-priori knowledge of libldap internal workings.
41 * hodges@stanford.edu 5-Feb-96
46 static char *get_line
LDAP_P(( char *line
, int len
, FILE *fp
, const char *prompt
));
47 static char **get_list
LDAP_P(( const char *prompt
));
48 static int file_read
LDAP_P(( const char *path
, struct berval
*bv
));
49 static LDAPMod
**get_modlist
LDAP_P(( const char *prompt1
,
50 const char *prompt2
, const char *prompt3
));
51 static void handle_result
LDAP_P(( LDAP
*ld
, LDAPMessage
*lm
));
52 static void print_ldap_result
LDAP_P(( LDAP
*ld
, LDAPMessage
*lm
,
54 static void print_search_entry
LDAP_P(( LDAP
*ld
, LDAPMessage
*res
));
55 static void free_list
LDAP_P(( char **list
));
57 static char *dnsuffix
;
60 get_line( char *line
, int len
, FILE *fp
, const char *prompt
)
62 fputs(prompt
, stdout
);
64 if ( fgets( line
, len
, fp
) == NULL
)
67 line
[ strlen( line
) - 1 ] = '\0';
73 get_list( const char *prompt
)
82 get_line( buf
, sizeof(buf
), stdin
, prompt
);
87 if ( result
== (char **) 0 )
88 result
= (char **) malloc( sizeof(char *) );
90 result
= (char **) realloc( result
,
91 sizeof(char *) * (num
+ 1) );
93 result
[num
++] = (char *) strdup( buf
);
95 if ( result
== (char **) 0 )
97 result
= (char **) realloc( result
, sizeof(char *) * (num
+ 1) );
105 free_list( char **list
)
109 if ( list
!= NULL
) {
110 for ( i
= 0; list
[ i
] != NULL
; ++i
) {
113 free( (char *)list
);
119 file_read( const char *path
, struct berval
*bv
)
125 if (( fp
= fopen( path
, "r" )) == NULL
) {
130 if ( fseek( fp
, 0L, SEEK_END
) != 0 ) {
136 bv
->bv_len
= ftell( fp
);
138 if (( bv
->bv_val
= (char *)malloc( bv
->bv_len
)) == NULL
) {
144 if ( fseek( fp
, 0L, SEEK_SET
) != 0 ) {
150 rlen
= fread( bv
->bv_val
, 1, bv
->bv_len
, fp
);
154 if ( (ber_len_t
) rlen
!= bv
->bv_len
) {
160 return( bv
->bv_len
);
168 const char *prompt3
)
170 static char buf
[256];
174 struct berval
**bvals
;
180 get_line( buf
, sizeof(buf
), stdin
, prompt1
);
181 tmp
.mod_op
= atoi( buf
);
183 if ( tmp
.mod_op
== -1 || buf
[0] == '\0' )
187 get_line( buf
, sizeof(buf
), stdin
, prompt2
);
188 if ( buf
[0] == '\0' )
190 tmp
.mod_type
= strdup( buf
);
192 tmp
.mod_values
= get_list( prompt3
);
194 if ( tmp
.mod_values
!= NULL
) {
197 for ( i
= 0; tmp
.mod_values
[i
] != NULL
; ++i
)
199 bvals
= (struct berval
**)calloc( i
+ 1,
200 sizeof( struct berval
*));
201 for ( i
= 0; tmp
.mod_values
[i
] != NULL
; ++i
) {
202 bvals
[i
] = (struct berval
*)malloc(
203 sizeof( struct berval
));
204 if ( strncmp( tmp
.mod_values
[i
], "{FILE}",
206 if ( file_read( tmp
.mod_values
[i
] + 6,
209 for ( i
= 0; i
<num
; i
++ )
215 bvals
[i
]->bv_val
= tmp
.mod_values
[i
];
217 strlen( tmp
.mod_values
[i
] );
220 tmp
.mod_bvalues
= bvals
;
221 tmp
.mod_op
|= LDAP_MOD_BVALUES
;
224 if ( result
== NULL
)
225 result
= (LDAPMod
**) malloc( sizeof(LDAPMod
*) );
227 result
= (LDAPMod
**) realloc( result
,
228 sizeof(LDAPMod
*) * (num
+ 1) );
230 result
[num
] = (LDAPMod
*) malloc( sizeof(LDAPMod
) );
231 *(result
[num
]) = tmp
; /* struct copy */
234 if ( result
== NULL
)
236 result
= (LDAPMod
**) realloc( result
, sizeof(LDAPMod
*) * (num
+ 1) );
244 bind_prompt( LDAP
*ld
,
245 LDAP_CONST
char *url
,
246 ber_tag_t request
, ber_int_t msgid
,
249 static char dn
[256], passwd
[256];
252 printf("rebind for request=%ld msgid=%ld url=%s\n",
253 request
, (long) msgid
, url
);
255 authmethod
= LDAP_AUTH_SIMPLE
;
257 get_line( dn
, sizeof(dn
), stdin
, "re-bind dn? " );
258 strcat( dn
, dnsuffix
);
260 if ( authmethod
== LDAP_AUTH_SIMPLE
&& dn
[0] != '\0' ) {
261 get_line( passwd
, sizeof(passwd
), stdin
,
262 "re-bind password? " );
267 return ldap_bind_s( ld
, dn
, passwd
, authmethod
);
272 main( int argc
, char **argv
)
275 int i
, c
, port
, errflg
, method
, id
, msgtype
;
276 char line
[256], command1
, command2
, command3
;
277 char passwd
[64], dn
[256], rdn
[64], attr
[64], value
[256];
278 char filter
[256], *host
, **types
;
280 static const char usage
[] =
281 "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
282 int bound
, all
, scope
, attrsonly
;
284 LDAPMod
**mods
, **attrs
;
285 struct timeval timeout
;
286 char *copyfname
= NULL
;
295 while (( c
= getopt( argc
, argv
, "h:d:s:p:t:T:" )) != -1 ) {
299 ldap_debug
= atoi( optarg
);
301 if ( ldap_debug
& LDAP_DEBUG_PACKETS
) {
302 ber_set_option( NULL
, LBER_OPT_DEBUG_LEVEL
, &ldap_debug
);
306 printf( "Compile with -DLDAP_DEBUG for debugging\n" );
319 port
= atoi( optarg
);
322 case 't': /* copy ber's to given file */
323 copyfname
= strdup( optarg
);
324 /* copyoptions = LBER_TO_FILE; */
327 case 'T': /* only output ber's to given file */
328 copyfname
= strdup( optarg
);
329 /* copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */
337 if ( host
== NULL
&& optind
== argc
- 1 ) {
338 host
= argv
[ optind
];
342 if ( errflg
|| optind
< argc
- 1 ) {
343 fprintf( stderr
, usage
, argv
[ 0 ] );
344 exit( EXIT_FAILURE
);
347 printf( "ldap_init( %s, %d )\n",
348 host
== NULL
? "(null)" : host
, port
);
350 ld
= ldap_init( host
, port
);
353 perror( "ldap_init" );
354 exit( EXIT_FAILURE
);
357 if ( copyfname
!= NULL
) {
358 if ( ( ld
->ld_sb
->sb_fd
= open( copyfname
, O_WRONLY
|O_CREAT
|O_EXCL
,
361 exit ( EXIT_FAILURE
);
363 ld
->ld_sb
->sb_options
= copyoptions
;
370 (void) memset( line
, '\0', sizeof(line
) );
371 while ( get_line( line
, sizeof(line
), stdin
, "\ncommand? " ) != NULL
) {
376 switch ( command1
) {
377 case 'a': /* add or abandon */
378 switch ( command2
) {
380 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
381 strcat( dn
, dnsuffix
);
382 if ( (attrs
= get_modlist( NULL
, "attr? ",
383 "value? " )) == NULL
)
385 if ( (id
= ldap_add( ld
, dn
, attrs
)) == -1 )
386 ldap_perror( ld
, "ldap_add" );
388 printf( "Add initiated with id %d\n",
392 case 'b': /* abandon */
393 get_line( line
, sizeof(line
), stdin
, "msgid? " );
395 if ( ldap_abandon( ld
, id
) != 0 )
396 ldap_perror( ld
, "ldap_abandon" );
398 printf( "Abandon successful\n" );
401 printf( "Possibilities: [ad]d, [ab]ort\n" );
405 case 'b': /* asynch bind */
406 method
= LDAP_AUTH_SIMPLE
;
407 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
408 strcat( dn
, dnsuffix
);
410 if ( method
== LDAP_AUTH_SIMPLE
&& dn
[0] != '\0' )
411 get_line( passwd
, sizeof(passwd
), stdin
,
416 if ( ldap_bind( ld
, dn
, passwd
, method
) == -1 ) {
417 fprintf( stderr
, "ldap_bind failed\n" );
418 ldap_perror( ld
, "ldap_bind" );
420 printf( "Bind initiated\n" );
425 case 'B': /* synch bind */
426 method
= LDAP_AUTH_SIMPLE
;
427 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
428 strcat( dn
, dnsuffix
);
431 get_line( passwd
, sizeof(passwd
), stdin
,
436 if ( ldap_bind_s( ld
, dn
, passwd
, method
) !=
438 fprintf( stderr
, "ldap_bind_s failed\n" );
439 ldap_perror( ld
, "ldap_bind_s" );
441 printf( "Bind successful\n" );
446 case 'c': /* compare */
447 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
448 strcat( dn
, dnsuffix
);
449 get_line( attr
, sizeof(attr
), stdin
, "attr? " );
450 get_line( value
, sizeof(value
), stdin
, "value? " );
452 if ( (id
= ldap_compare( ld
, dn
, attr
, value
)) == -1 )
453 ldap_perror( ld
, "ldap_compare" );
455 printf( "Compare initiated with id %d\n", id
);
458 case 'd': /* turn on debugging */
460 get_line( line
, sizeof(line
), stdin
, "debug level? " );
461 ldap_debug
= atoi( line
);
463 if ( ldap_debug
& LDAP_DEBUG_PACKETS
) {
464 ber_set_option( NULL
, LBER_OPT_DEBUG_LEVEL
, &ldap_debug
);
468 printf( "Compile with -DLDAP_DEBUG for debugging\n" );
472 case 'E': /* explode a dn */
473 get_line( line
, sizeof(line
), stdin
, "dn? " );
474 exdn
= ldap_explode_dn( line
, 0 );
475 for ( i
= 0; exdn
!= NULL
&& exdn
[i
] != NULL
; i
++ ) {
476 printf( "\t%s\n", exdn
[i
] );
480 case 'g': /* set next msgid */
481 get_line( line
, sizeof(line
), stdin
, "msgid? " );
482 ld
->ld_msgid
= atoi( line
);
485 case 'v': /* set version number */
486 get_line( line
, sizeof(line
), stdin
, "version? " );
487 ld
->ld_version
= atoi( line
);
490 case 'm': /* modify or modifyrdn */
491 if ( strncmp( line
, "modify", 4 ) == 0 ) {
492 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
493 strcat( dn
, dnsuffix
);
494 if ( (mods
= get_modlist(
495 "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ",
496 "attribute type? ", "attribute value? " ))
499 if ( (id
= ldap_modify( ld
, dn
, mods
)) == -1 )
500 ldap_perror( ld
, "ldap_modify" );
502 printf( "Modify initiated with id %d\n",
504 } else if ( strncmp( line
, "modrdn", 4 ) == 0 ) {
505 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
506 strcat( dn
, dnsuffix
);
507 get_line( rdn
, sizeof(rdn
), stdin
, "newrdn? " );
508 if ( (id
= ldap_modrdn( ld
, dn
, rdn
)) == -1 )
509 ldap_perror( ld
, "ldap_modrdn" );
511 printf( "Modrdn initiated with id %d\n",
514 printf( "Possibilities: [modi]fy, [modr]dn\n" );
520 exit( EXIT_SUCCESS
);
523 case 'r': /* result or remove */
524 switch ( command3
) {
525 case 's': /* result */
526 get_line( line
, sizeof(line
), stdin
,
527 "msgid (-1=>any)? " );
528 if ( line
[0] == '\0' )
532 get_line( line
, sizeof(line
), stdin
,
533 "all (0=>any, 1=>all)? " );
534 if ( line
[0] == '\0' )
538 if (( msgtype
= ldap_result( ld
, id
, all
,
539 &timeout
, &res
)) < 1 ) {
540 ldap_perror( ld
, "ldap_result" );
543 printf( "\nresult: msgtype %d msgid %d\n",
544 msgtype
, res
->lm_msgid
);
545 handle_result( ld
, res
);
549 case 'm': /* remove */
550 get_line( dn
, sizeof(dn
), stdin
, "dn? " );
551 strcat( dn
, dnsuffix
);
552 if ( (id
= ldap_delete( ld
, dn
)) == -1 )
553 ldap_perror( ld
, "ldap_delete" );
555 printf( "Remove initiated with id %d\n",
560 printf( "Possibilities: [rem]ove, [res]ult\n" );
565 case 's': /* search */
566 get_line( dn
, sizeof(dn
), stdin
, "searchbase? " );
567 strcat( dn
, dnsuffix
);
568 get_line( line
, sizeof(line
), stdin
,
569 "scope (0=baseObject, 1=oneLevel, 2=subtree, 3=children)? " );
570 scope
= atoi( line
);
571 get_line( filter
, sizeof(filter
), stdin
,
572 "search filter (e.g. sn=jones)? " );
573 types
= get_list( "attrs to return? " );
574 get_line( line
, sizeof(line
), stdin
,
575 "attrsonly (0=attrs&values, 1=attrs only)? " );
576 attrsonly
= atoi( line
);
578 if (( id
= ldap_search( ld
, dn
, scope
, filter
,
579 types
, attrsonly
)) == -1 ) {
580 ldap_perror( ld
, "ldap_search" );
582 printf( "Search initiated with id %d\n", id
);
587 case 't': /* set timeout value */
588 get_line( line
, sizeof(line
), stdin
, "timeout? " );
589 timeout
.tv_sec
= atoi( line
);
592 case 'p': /* parse LDAP URL */
593 get_line( line
, sizeof(line
), stdin
, "LDAP URL? " );
594 if (( i
= ldap_url_parse( line
, &ludp
)) != 0 ) {
595 fprintf( stderr
, "ldap_url_parse: error %d\n", i
);
597 printf( "\t host: " );
598 if ( ludp
->lud_host
== NULL
) {
599 printf( "DEFAULT\n" );
601 printf( "<%s>\n", ludp
->lud_host
);
603 printf( "\t port: " );
604 if ( ludp
->lud_port
== 0 ) {
605 printf( "DEFAULT\n" );
607 printf( "%d\n", ludp
->lud_port
);
609 printf( "\t dn: <%s>\n", ludp
->lud_dn
);
610 printf( "\t attrs:" );
611 if ( ludp
->lud_attrs
== NULL
) {
614 for ( i
= 0; ludp
->lud_attrs
[ i
] != NULL
; ++i
) {
615 printf( " <%s>", ludp
->lud_attrs
[ i
] );
618 printf( "\n\t scope: %s\n",
619 ludp
->lud_scope
== LDAP_SCOPE_BASE
? "baseObject"
620 : ludp
->lud_scope
== LDAP_SCOPE_ONELEVEL
? "oneLevel"
621 : ludp
->lud_scope
== LDAP_SCOPE_SUBTREE
? "subtree"
622 #ifdef LDAP_SCOPE_SUBORDINATE
623 : ludp
->lud_scope
== LDAP_SCOPE_SUBORDINATE
? "children"
626 printf( "\tfilter: <%s>\n", ludp
->lud_filter
);
627 ldap_free_urldesc( ludp
);
631 case 'n': /* set dn suffix, for convenience */
632 get_line( line
, sizeof(line
), stdin
, "DN suffix? " );
633 strcpy( dnsuffix
, line
);
636 case 'o': /* set ldap options */
637 get_line( line
, sizeof(line
), stdin
, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" );
638 ld
->ld_deref
= atoi( line
);
639 get_line( line
, sizeof(line
), stdin
, "timelimit?" );
640 ld
->ld_timelimit
= atoi( line
);
641 get_line( line
, sizeof(line
), stdin
, "sizelimit?" );
642 ld
->ld_sizelimit
= atoi( line
);
644 LDAP_BOOL_ZERO(&ld
->ld_options
);
646 get_line( line
, sizeof(line
), stdin
,
647 "Recognize and chase referrals (0=no, 1=yes)?" );
648 if ( atoi( line
) != 0 ) {
649 LDAP_BOOL_SET(&ld
->ld_options
, LDAP_BOOL_REFERRALS
);
650 get_line( line
, sizeof(line
), stdin
,
651 "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" );
652 if ( atoi( line
) != 0 ) {
653 ldap_set_rebind_proc( ld
, bind_prompt
, NULL
);
660 "Commands: [ad]d [ab]andon [b]ind\n"
661 " [B]ind async [c]ompare\n"
662 " [modi]fy [modr]dn [rem]ove\n"
663 " [res]ult [s]earch [q]uit/unbind\n\n"
664 " [d]ebug set ms[g]id\n"
665 " d[n]suffix [t]imeout [v]ersion\n"
667 " [E]xplode dn [p]arse LDAP URL\n" );
671 printf( "Invalid command. Type ? for help.\n" );
675 (void) memset( line
, '\0', sizeof(line
) );
682 handle_result( LDAP
*ld
, LDAPMessage
*lm
)
684 switch ( lm
->lm_msgtype
) {
685 case LDAP_RES_COMPARE
:
686 printf( "Compare result\n" );
687 print_ldap_result( ld
, lm
, "compare" );
690 case LDAP_RES_SEARCH_RESULT
:
691 printf( "Search result\n" );
692 print_ldap_result( ld
, lm
, "search" );
695 case LDAP_RES_SEARCH_ENTRY
:
696 printf( "Search entry\n" );
697 print_search_entry( ld
, lm
);
701 printf( "Add result\n" );
702 print_ldap_result( ld
, lm
, "add" );
705 case LDAP_RES_DELETE
:
706 printf( "Delete result\n" );
707 print_ldap_result( ld
, lm
, "delete" );
710 case LDAP_RES_MODRDN
:
711 printf( "ModRDN result\n" );
712 print_ldap_result( ld
, lm
, "modrdn" );
716 printf( "Bind result\n" );
717 print_ldap_result( ld
, lm
, "bind" );
721 printf( "Unknown result type 0x%lx\n",
722 (unsigned long) lm
->lm_msgtype
);
723 print_ldap_result( ld
, lm
, "unknown" );
728 print_ldap_result( LDAP
*ld
, LDAPMessage
*lm
, const char *s
)
730 ldap_result2error( ld
, lm
, 1 );
731 ldap_perror( ld
, s
);
733 if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
734 fprintf( stderr, "Additional info: %s\n", ld->ld_error );
735 if ( LDAP_NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
736 fprintf( stderr, "Matched DN: %s\n", ld->ld_matched );
741 print_search_entry( LDAP
*ld
, LDAPMessage
*res
)
745 for ( e
= ldap_first_entry( ld
, res
); e
!= NULL
;
746 e
= ldap_next_entry( ld
, e
) )
748 BerElement
*ber
= NULL
;
751 if ( e
->lm_msgtype
== LDAP_RES_SEARCH_RESULT
)
754 dn
= ldap_get_dn( ld
, e
);
755 printf( "\tDN: %s\n", dn
);
757 ufn
= ldap_dn2ufn( dn
);
758 printf( "\tUFN: %s\n", ufn
);
763 for ( a
= ldap_first_attribute( ld
, e
, &ber
); a
!= NULL
;
764 a
= ldap_next_attribute( ld
, e
, ber
) )
766 struct berval
**vals
;
768 printf( "\t\tATTR: %s\n", a
);
769 if ( (vals
= ldap_get_values_len( ld
, e
, a
))
771 printf( "\t\t\t(no values)\n" );
774 for ( i
= 0; vals
[i
] != NULL
; i
++ ) {
778 for ( j
= 0; (ber_len_t
) j
< vals
[i
]->bv_len
; j
++ )
779 if ( !isascii( vals
[i
]->bv_val
[j
] ) ) {
785 printf( "\t\t\tlength (%ld) (not ascii)\n", vals
[i
]->bv_len
);
786 #ifdef BPRINT_NONASCII
787 ber_bprint( vals
[i
]->bv_val
,
789 #endif /* BPRINT_NONASCII */
792 printf( "\t\t\tlength (%ld) %s\n",
793 vals
[i
]->bv_len
, vals
[i
]->bv_val
);
795 ber_bvecfree( vals
);
804 if ( res
->lm_msgtype
== LDAP_RES_SEARCH_RESULT
805 || res
->lm_chain
!= NULL
)
806 print_ldap_result( ld
, res
, "search" );