X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=clients%2Ftools%2Fcommon.c;h=8cbb480eb3561aba19715ed6907007bdd233689e;hb=fe342e2be3661ce6fed146e1959298b6731b75a5;hp=88fe29db48780fef935937a448f2f1565a194d0a;hpb=a9b4c04f1ca3a64a22c1345c2a7562c1985e14f4;p=openldap diff --git a/clients/tools/common.c b/clients/tools/common.c index 88fe29db48..8cbb480eb3 100644 --- a/clients/tools/common.c +++ b/clients/tools/common.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2007 The OpenLDAP Foundation. + * Copyright 1998-2009 The OpenLDAP Foundation. * Portions Copyright 2003 Kurt D. Zeilenga. * Portions Copyright 2003 IBM Corporation. * All rights reserved. @@ -62,6 +62,7 @@ int contoper = 0; int debug = 0; char *infile = NULL; int dont = 0; +int nocanon = 0; int referrals = 0; int verbose = 0; int ldif = 0; @@ -93,6 +94,7 @@ char *sasl_secprops = NULL; /* controls */ int assertctl; char *assertion = NULL; +struct berval assertionvalue = BER_BVNULL; char *authzid = NULL; /* support deprecated early version of proxyAuthz */ #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12" @@ -118,6 +120,9 @@ static int chainingContinuation = -1; static int sessionTracking = 0; struct berval stValue; #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ +ber_int_t vlvPos; +ber_int_t vlvCount; +struct berval *vlvContext; LDAPControl *unknown_ctrls = NULL; int unknown_ctrls_num = 0; @@ -133,6 +138,14 @@ static int print_paged_results( LDAP *ld, LDAPControl *ctrl ); #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST static int print_ppolicy( LDAP *ld, LDAPControl *ctrl ); #endif +static int print_sss( LDAP *ld, LDAPControl *ctrl ); +static int print_vlv( LDAP *ld, LDAPControl *ctrl ); +#ifdef LDAP_CONTROL_X_DEREF +static int print_deref( LDAP *ld, LDAPControl *ctrl ); +#endif +#ifdef LDAP_CONTROL_X_WHATFAILED +static int print_whatfailed( LDAP *ld, LDAPControl *ctrl ); +#endif static struct tool_ctrls_t { const char *oid; @@ -144,13 +157,68 @@ static struct tool_ctrls_t { { LDAP_CONTROL_PAGEDRESULTS, TOOL_SEARCH, print_paged_results }, #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST { LDAP_CONTROL_PASSWORDPOLICYRESPONSE, TOOL_ALL, print_ppolicy }, +#endif + { LDAP_CONTROL_SORTRESPONSE, TOOL_SEARCH, print_sss }, + { LDAP_CONTROL_VLVRESPONSE, TOOL_SEARCH, print_vlv }, +#ifdef LDAP_CONTROL_X_DEREF + { LDAP_CONTROL_X_DEREF, TOOL_SEARCH, print_deref }, +#endif +#ifdef LDAP_CONTROL_X_WHATFAILED + { LDAP_CONTROL_X_WHATFAILED, TOOL_ALL, print_whatfailed }, #endif { NULL, 0, NULL } }; /* "features" */ -static int gotintr; -static int abcan; +enum { Intr_None = 0, Intr_Abandon, Intr_Cancel, Intr_Ignore }; +static volatile sig_atomic_t gotintr, abcan; + + +#ifdef LDAP_CONTROL_X_SESSION_TRACKING +static int +st_value( LDAP *ld, struct berval *value ) +{ + char *ip = NULL, *name = NULL; + struct berval id = { 0 }; + char namebuf[ MAXHOSTNAMELEN ]; + + if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) { + struct hostent *h; + struct in_addr addr; + + name = namebuf; + + h = gethostbyname( name ); + if ( h != NULL ) { + AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) ); + ip = inet_ntoa( addr ); + } + } + +#ifdef HAVE_CYRUS_SASL + if ( sasl_authz_id != NULL ) { + ber_str2bv( sasl_authz_id, 0, 0, &id ); + + } else if ( sasl_authc_id != NULL ) { + ber_str2bv( sasl_authc_id, 0, 0, &id ); + + } else +#endif /* HAVE_CYRUS_SASL */ + if ( binddn != NULL ) { + ber_str2bv( binddn, 0, 0, &id ); + } + + if ( ldap_create_session_tracking_value( ld, + ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME, + &id, &stValue ) ) + { + fprintf( stderr, _("Session tracking control encoding error!\n") ); + return -1; + } + + return 0; +} +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ RETSIGTYPE do_sig( int sig ) @@ -176,18 +244,38 @@ tool_destroy( void ) #ifdef HAVE_TLS ldap_pvt_tls_destroy(); #endif + + if ( ldapuri != NULL ) { + ber_memfree( ldapuri ); + ldapuri = NULL; + } + + if ( pr_cookie.bv_val != NULL ) { + ber_memfree( pr_cookie.bv_val ); + pr_cookie.bv_val = NULL; + pr_cookie.bv_len = 0; + } + + if ( binddn != NULL ) { + ber_memfree( binddn ); + } + +#if 0 /* not yet */ + if ( passwd.bv_val != NULL ) { + ber_memfree( passwd.bv_val ); + } +#endif } void tool_common_usage( void ) { static const char *const descriptions[] = { -N_(" -c continuous operation mode (do not stop on errors)\n"), N_(" -d level set LDAP debugging level to `level'\n"), N_(" -D binddn bind DN\n"), N_(" -e [!][=] general extensions (! indicates criticality)\n") -N_(" [!]assert= (a RFC 4515 Filter string)\n") -N_(" [!]authzid= (\"dn:\" or \"u:\")\n") +N_(" [!]assert= (RFC 4528; a RFC 4515 Filter string)\n") +N_(" [!]authzid= (RFC 4370; \"dn:\" or \"u:\")\n") #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ #if 0 /* non-advertized support for proxyDN */ @@ -199,33 +287,29 @@ N_(" [!]chaining[=[/]]\n") N_(" one of \"chainingPreferred\", \"chainingRequired\",\n") N_(" \"referralsPreferred\", \"referralsRequired\"\n") #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ -N_(" [!]manageDSAit\n") +N_(" [!]manageDSAit (RFC 3296)\n") N_(" [!]noop\n") #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST N_(" ppolicy\n") #endif -N_(" [!]postread[=] (a comma-separated attribute list)\n") -N_(" [!]preread[=] (a comma-separated attribute list)\n") -#ifdef LDAP_DEVEL +N_(" [!]postread[=] (RFC 4527; comma-separated attr list)\n") +N_(" [!]preread[=] (RFC 4527; comma-separated attr list)\n") N_(" [!]relax\n") -#endif #ifdef LDAP_CONTROL_X_SESSION_TRACKING N_(" [!]sessiontracking\n") #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ N_(" abandon, cancel, ignore (SIGINT sends abandon/cancel,\n" " or ignores response; if critical, doesn't wait for SIGINT.\n" " not really controls)\n") -N_(" -f file read operations from `file'\n"), N_(" -h host LDAP server\n"), N_(" -H URI LDAP Uniform Resource Identifier(s)\n"), N_(" -I use SASL Interactive mode\n"), -N_(" -M enable Manage DSA IT control (-MM to make critical)\n"), N_(" -n show what would be done but don't actually do it\n"), +N_(" -N do not use reverse DNS to canonicalize SASL host name\n"), N_(" -O props SASL security properties\n"), N_(" -o [= (in seconds, or \"none\" or \"max\")\n"), N_(" -p port port on LDAP server\n"), -N_(" -P version protocol version (default: 3)\n"), N_(" -Q use SASL Quiet mode\n"), N_(" -R realm SASL realm\n"), N_(" -U authcid SASL authentication identity\n"), @@ -513,19 +597,19 @@ tool_args( int argc, char **argv ) /* this shouldn't go here, really; but it's a feature... */ } else if ( strcasecmp( control, "abandon" ) == 0 ) { - abcan = LDAP_REQ_ABANDON; + abcan = Intr_Abandon; if ( crit ) { gotintr = abcan; } } else if ( strcasecmp( control, "cancel" ) == 0 ) { - abcan = LDAP_REQ_EXTENDED; + abcan = Intr_Cancel; if ( crit ) { gotintr = abcan; } } else if ( strcasecmp( control, "ignore" ) == 0 ) { - abcan = -1; + abcan = Intr_Ignore; if ( crit ) { gotintr = abcan; } @@ -542,7 +626,7 @@ tool_args( int argc, char **argv ) } else if ( tool_is_oid( control ) ) { LDAPControl *tmpctrls, ctrl; - tmpctrls = (LDAPControl *)realloc( unknown_ctrls, + tmpctrls = (LDAPControl *)ber_memrealloc( unknown_ctrls, (unknown_ctrls_num + 1)*sizeof( LDAPControl ) ); if ( tmpctrls == NULL ) { fprintf( stderr, "%s: no memory?\n", prog ); @@ -566,7 +650,7 @@ tool_args( int argc, char **argv ) (unsigned char *)bv.bv_val, bv.bv_len ); - if ( retcode == -1 || retcode > bv.bv_len ) { + if ( retcode == -1 || (unsigned) retcode > bv.bv_len ) { fprintf( stderr, "Unable to parse value of general control %s\n", control ); usage(); @@ -629,6 +713,9 @@ tool_args( int argc, char **argv ) case 'n': /* print operations, don't actually do them */ dont++; break; + case 'N': + nocanon++; + break; case 'o': control = ber_strdup( optarg ); if ( (cvalue = strchr( control, '=' )) != NULL ) { @@ -701,7 +788,7 @@ tool_args( int argc, char **argv ) case 'P': ival = strtol( optarg, &next, 10 ); if ( next == NULL || next[0] != '\0' ) { - fprintf( stderr, "%s: unabel to parse protocol version \"%s\"\n", prog, optarg ); + fprintf( stderr, "%s: unable to parse protocol version \"%s\"\n", prog, optarg ); exit( EXIT_FAILURE ); } switch( ival ) { @@ -922,7 +1009,11 @@ tool_args( int argc, char **argv ) if (authmethod == -1 && protocol > LDAP_VERSION2) { #ifdef HAVE_CYRUS_SASL - authmethod = LDAP_AUTH_SASL; + if ( binddn != NULL ) { + authmethod = LDAP_AUTH_SIMPLE; + } else { + authmethod = LDAP_AUTH_SASL; + } #else authmethod = LDAP_AUTH_SIMPLE; #endif @@ -1081,7 +1172,7 @@ tool_conn_setup( int dont, void (*private_setup)( LDAP * ) ) for ( i = 0; hosts[ i ] != NULL; i++ ) /* count'em */ ; - tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + i + 1 ) ); + tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + i + 1 ) ); if ( tmp == NULL ) { fprintf( stderr, "DNS SRV: out of memory?\n" ); @@ -1115,7 +1206,7 @@ dnssrv_free:; ber_memfree( domain ); } else { - tmp = (char **)realloc( urls, sizeof( char * ) * ( nurls + 2 ) ); + tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + 2 ) ); if ( tmp == NULL ) { fprintf( stderr, "DNS SRV: out of memory?\n" ); @@ -1175,6 +1266,16 @@ dnssrv_free:; exit( EXIT_FAILURE ); } +#ifdef HAVE_CYRUS_SASL + /* canon */ + if( ldap_set_option( ld, LDAP_OPT_X_SASL_NOCANON, + nocanon ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_NOCANON %s\n", + nocanon ? "on" : "off" ); + exit( EXIT_FAILURE ); + } +#endif if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) { @@ -1186,7 +1287,10 @@ dnssrv_free:; if ( use_tls ) { rc = ldap_start_tls_s( ld, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { - tool_perror( "ldap_start_tls", rc, NULL, NULL, NULL, NULL ); + char *msg=NULL; + ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); + tool_perror( "ldap_start_tls", rc, NULL, NULL, msg, NULL ); + ldap_memfree(msg); if ( use_tls > 1 ) { exit( EXIT_FAILURE ); } @@ -1232,55 +1336,14 @@ tool_bind( LDAP *ld ) #ifdef LDAP_CONTROL_X_SESSION_TRACKING if ( sessionTracking ) { LDAPControl c; - char *ip = NULL, *name = NULL; - struct berval id = { 0 }, prefix_id; - char namebuf[ MAXHOSTNAMELEN ]; - char *ptr; - - if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) { - struct hostent *h; - struct in_addr addr; - - name = namebuf; - - h = gethostbyname( name ); - if ( h != NULL ) { - AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) ); - ip = inet_ntoa( addr ); - } - } - -#ifdef HAVE_CYRUS_SASL - if ( sasl_authz_id != NULL ) { - ber_str2bv( sasl_authz_id, 0, 0, &id ); - - } else if ( sasl_authc_id != NULL ) { - ber_str2bv( sasl_authc_id, 0, 0, &id ); - - } else -#endif /* HAVE_CYRUS_SASL */ - if ( binddn != NULL ) { - ber_str2bv( binddn, 0, 0, &id ); - } else { - ber_str2bv( "anonymous", 0, 0, &id ); - } - - prefix_id.bv_len = STRLENOF( "binding:" ) + id.bv_len; - ptr = prefix_id.bv_val = malloc ( prefix_id.bv_len + 1 ); - ptr = lutil_strcopy( ptr, "binding:" ); - ptr = lutil_strcopy(ptr, id.bv_val ); - - if ( ldap_create_session_tracking_value( ld, - ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME, - &prefix_id, &c.ldctl_value ) ) - { - fprintf( stderr, _("Session tracking control encoding error!\n") ); + if (stValue.bv_val == NULL && st_value( ld, &stValue ) ) { exit( EXIT_FAILURE ); } c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; c.ldctl_iscritical = 0; + ber_dupbv( &c.ldctl_value, &stValue ); sctrl[nsctrls] = c; sctrls[nsctrls] = &sctrl[nsctrls]; @@ -1292,7 +1355,7 @@ tool_bind( LDAP *ld ) sctrlsp = sctrls; } - assert( nsctrls < sizeof(sctrls)/sizeof(sctrls[0]) ); + assert( nsctrls < (int) (sizeof(sctrls)/sizeof(sctrls[0])) ); if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL @@ -1324,8 +1387,11 @@ tool_bind( LDAP *ld ) lutil_sasl_freedefs( defaults ); if( rc != LDAP_SUCCESS ) { + char *msg=NULL; + ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); tool_perror( "ldap_sasl_interactive_bind_s", - rc, NULL, NULL, NULL, NULL ); + rc, NULL, NULL, msg, NULL ); + ldap_memfree(msg); exit( rc ); } #else @@ -1354,11 +1420,17 @@ tool_bind( LDAP *ld ) } } - if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( rc == -1 ) { tool_perror( "ldap_result", -1, NULL, NULL, NULL, NULL ); exit( LDAP_LOCAL_ERROR ); } + if ( rc == 0 ) { + tool_perror( "ldap_result", LDAP_TIMEOUT, NULL, NULL, NULL, NULL ); + exit( LDAP_LOCAL_ERROR ); + } + rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs, &ctrls, 1 ); if ( rc != LDAP_SUCCESS ) { @@ -1372,8 +1444,8 @@ tool_bind( LDAP *ld ) int expire, grace, len = 0; LDAPPasswordPolicyError pErr = -1; - ctrl = ldap_find_control( LDAP_CONTROL_PASSWORDPOLICYRESPONSE, - ctrls ); + ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE, + ctrls, NULL ); if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl, &expire, &grace, &pErr ) == LDAP_SUCCESS ) @@ -1470,29 +1542,18 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) } if ( assertctl ) { - BerElementBuffer berbuf; - BerElement *ber = (BerElement *)&berbuf; - - if( assertion == NULL || *assertion == '\0' ) { - fprintf( stderr, "Assertion=\n" ); - exit( EXIT_FAILURE ); - } - - ber_init2( ber, NULL, LBER_USE_DER ); - - err = ldap_pvt_put_filter( ber, assertion ); - if( err < 0 ) { - fprintf( stderr, "assertion encode failed (%d)\n", err ); - exit( EXIT_FAILURE ); - } - - err = ber_flatten2( ber, &c[i].ldctl_value, 0 ); - if( err < 0 ) { - fprintf( stderr, "assertion flatten failed (%d)\n", err ); - exit( EXIT_FAILURE ); + if ( BER_BVISNULL( &assertionvalue ) ) { + err = ldap_create_assertion_control_value( ld, + assertion, &assertionvalue ); + if ( err ) { + fprintf( stderr, + "Unable to create assertion value " + "\"%s\" (%d)\n", assertion, err ); + } } c[i].ldctl_oid = LDAP_CONTROL_ASSERT; + c[i].ldctl_value = assertionvalue; c[i].ldctl_iscritical = assertctl > 1; ctrls[i] = &c[i]; i++; @@ -1516,7 +1577,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) ber_init2( ber, NULL, LBER_USE_DER ); - if ( ber_printf( ber, "s", proxydn ) == LBER_ERROR ) { + if ( ber_printf( ber, "s", proxydn ) == -1 ) { exit( EXIT_FAILURE ); } @@ -1566,8 +1627,8 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) #endif if ( preread ) { - char berbuf[LBER_ELEMENT_SIZEOF]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; char **attrs = NULL; if( preread_attrs ) { @@ -1596,8 +1657,8 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) } if ( postread ) { - char berbuf[LBER_ELEMENT_SIZEOF]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; char **attrs = NULL; if( postread_attrs ) { @@ -1673,52 +1734,14 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) #ifdef LDAP_CONTROL_X_SESSION_TRACKING if ( sessionTracking ) { - if ( stValue.bv_val == NULL ) { - char *ip = NULL, *name = NULL; - struct berval id = { 0 }; - char namebuf[ MAXHOSTNAMELEN ]; - - if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) { - struct hostent *h; - struct in_addr addr; - - name = namebuf; - - h = gethostbyname( name ); - if ( h != NULL ) { - AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) ); - ip = inet_ntoa( addr ); - } - } - -#ifdef HAVE_CYRUS_SASL - if ( sasl_authz_id != NULL ) { - ber_str2bv( sasl_authz_id, 0, 0, &id ); - - } else if ( sasl_authc_id != NULL ) { - ber_str2bv( sasl_authc_id, 0, 0, &id ); - - } else -#endif /* HAVE_CYRUS_SASL */ - if ( binddn != NULL ) { - ber_str2bv( binddn, 0, 0, &id ); - - } else { - ber_str2bv( "anonymous", 0, 0, &id ); - } - - if ( ldap_create_session_tracking_value( ld, - ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME, - &id, &stValue ) ) - { - fprintf( stderr, _("Session tracking control encoding error!\n") ); - exit( EXIT_FAILURE ); - } + if ( stValue.bv_val == NULL && st_value( ld, &stValue ) ) { + exit( EXIT_FAILURE ); } c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; c[i].ldctl_iscritical = 0; ber_dupbv( &c[i].ldctl_value, &stValue ); + ctrls[i] = &c[i]; i++; } @@ -1754,19 +1777,19 @@ tool_check_abandon( LDAP *ld, int msgid ) int rc; switch ( gotintr ) { - case LDAP_REQ_EXTENDED: + case Intr_Cancel: rc = ldap_cancel_s( ld, msgid, NULL, NULL ); fprintf( stderr, "got interrupt, cancel got %d: %s\n", rc, ldap_err2string( rc ) ); return -1; - case LDAP_REQ_ABANDON: + case Intr_Abandon: rc = ldap_abandon_ext( ld, msgid, NULL, NULL ); fprintf( stderr, "got interrupt, abandon got %d: %s\n", rc, ldap_err2string( rc ) ); return -1; - case -1: + case Intr_Ignore: /* just unbind, ignoring the request */ return -1; } @@ -1897,6 +1920,190 @@ print_paged_results( LDAP *ld, LDAPControl *ctrl ) return 0; } +static int +print_sss( LDAP *ld, LDAPControl *ctrl ) +{ + int rc; + ber_int_t err; + char *attr; + + rc = ldap_parse_sortresponse_control( ld, ctrl, &err, &attr ); + if ( rc == LDAP_SUCCESS ) { + char buf[ BUFSIZ ]; + rc = snprintf( buf, sizeof(buf), "(%d) %s%s%s", + err, ldap_err2string(err), attr ? " " : "", attr ? attr : "" ); + + tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "sortResult", buf, rc ); + } + + return rc; +} + +static int +print_vlv( LDAP *ld, LDAPControl *ctrl ) +{ + int rc; + ber_int_t err; + struct berval bv; + + rc = ldap_parse_vlvresponse_control( ld, ctrl, &vlvPos, &vlvCount, + &vlvContext, &err ); + if ( rc == LDAP_SUCCESS ) { + char buf[ BUFSIZ ]; + + if ( vlvContext && vlvContext->bv_len > 0 ) { + bv.bv_len = LUTIL_BASE64_ENCODE_LEN( + vlvContext->bv_len ) + 1; + bv.bv_val = ber_memalloc( bv.bv_len + 1 ); + + bv.bv_len = lutil_b64_ntop( + (unsigned char *) vlvContext->bv_val, + vlvContext->bv_len, + bv.bv_val, bv.bv_len ); + } else { + bv.bv_val = ""; + bv.bv_len = 0; + } + + rc = snprintf( buf, sizeof(buf), "pos=%d count=%d context=%s (%d) %s", + vlvPos, vlvCount, bv.bv_val, + err, ldap_err2string(err)); + + if ( bv.bv_len ) + ber_memfree( bv.bv_val ); + + tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "vlvResult", buf, rc ); + } + + return rc; +} + +#ifdef LDAP_CONTROL_X_DEREF +static int +print_deref( LDAP *ld, LDAPControl *ctrl ) +{ + LDAPDerefRes *drhead = NULL, *dr; + int rc; + + rc = ldap_parse_derefresponse_control( ld, ctrl, &drhead ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } + + for ( dr = drhead; dr != NULL; dr = dr->next ) { + LDAPDerefVal *dv; + ber_len_t len; + char *buf, *ptr; + + len = strlen( dr->derefAttr ) + STRLENOF(": "); + + for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) { + if ( dv->vals != NULL ) { + int j; + ber_len_t tlen = strlen(dv->type); + + for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) { + len += STRLENOF("<:=>;") + tlen + 4*((dv->vals[ j ].bv_len - 1)/3 + 1); + } + } + } + len += dr->derefVal.bv_len + STRLENOF("\n"); + buf = ldap_memalloc( len + 1 ); + if ( buf == NULL ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + ptr = buf; + ptr = lutil_strcopy( ptr, dr->derefAttr ); + *ptr++ = ':'; + *ptr++ = ' '; + for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) { + if ( dv->vals != NULL ) { + int j; + for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) { + int k = ldif_is_not_printable( dv->vals[ j ].bv_val, dv->vals[ j ].bv_len ); + + *ptr++ = '<'; + ptr = lutil_strcopy( ptr, dv->type ); + if ( k ) { + *ptr++ = ':'; + } + *ptr++ = '='; + if ( k ) { + k = lutil_b64_ntop( + (unsigned char *) dv->vals[ j ].bv_val, + dv->vals[ j ].bv_len, + ptr, buf + len - ptr ); + assert( k >= 0 ); + ptr += k; + + } else { + ptr = lutil_memcopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len ); + } + *ptr++ = '>'; + *ptr++ = ';'; + } + } + } + ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len ); + *ptr++ = '\n'; + *ptr = '\0'; + assert( ptr <= buf + len ); + + tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, ptr - buf); + + ldap_memfree( buf ); + } + + rc = LDAP_SUCCESS; + +done:; + ldap_derefresponse_free( drhead ); + + return rc; +} +#endif + +#ifdef LDAP_CONTROL_X_WHATFAILED +static int +print_whatfailed( LDAP *ld, LDAPControl *ctrl ) +{ + BerElement *ber; + ber_tag_t tag; + ber_len_t siz; + BerVarray bva = NULL; + + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init( &ctrl->ldctl_value ); + + if ( ber == NULL ) { + return LDAP_NO_MEMORY; + } + + siz = sizeof(struct berval); + tag = ber_scanf( ber, "[M]", &bva, &siz, 0 ); + if ( tag != LBER_ERROR ) { + int i; + + tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 ); + + for ( i = 0; bva[i].bv_val != NULL; i++ ) { + tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len ); + } + + ldap_memfree( bva ); + } + + ber_free( ber, 1 ); + + + return 0; +} +#endif + #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST static int print_ppolicy( LDAP *ld, LDAPControl *ctrl )