+ if ( authmethod == LDAP_AUTH_SASL ) {
+#ifdef HAVE_CYRUS_SASL
+ void *defaults;
+
+ if( sasl_secprops != NULL ) {
+ rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+ (void *) sasl_secprops );
+
+ if( rc != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr,
+ "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+ sasl_secprops );
+ return( EXIT_FAILURE );
+ }
+ }
+
+ defaults = lutil_sasl_defaults( ld,
+ sasl_mech,
+ sasl_realm,
+ sasl_authc_id,
+ passwd.bv_val,
+ sasl_authz_id );
+
+ rc = ldap_sasl_interactive_bind_s( ld, binddn,
+ sasl_mech, NULL, NULL,
+ sasl_flags, lutil_sasl_interact, defaults );
+
+ if( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
+ return( EXIT_FAILURE );
+ }
+#else
+ fprintf( stderr, "%s: not compiled with SASL support\n",
+ argv[0] );
+ return( EXIT_FAILURE );
+#endif
+ }
+ else {
+ if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
+ != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ return( EXIT_FAILURE );
+ }
+ }
+
+ if( dn != NULL || oldpw != NULL || newpw != NULL ) {
+ /* build change password control */
+ BerElement *ber = ber_alloc_t( LBER_USE_DER );
+
+ if( ber == NULL ) {
+ perror( "ber_alloc_t" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ ber_printf( ber, "{" /*}*/ );
+
+ if( dn != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
+ free(dn);
+ }
+
+ if( oldpw != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
+ free(oldpw);
+ }
+
+ if( newpw != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+ free(newpw);
+ }
+
+ ber_printf( ber, /*{*/ "N}" );
+
+ rc = ber_flatten( ber, &bv );
+
+ if( rc < 0 ) {
+ perror( "ber_flatten" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ ber_free( ber, 1 );
+ }
+
+ if ( not ) {
+ rc = LDAP_SUCCESS;
+ goto skip;
+ }
+
+ rc = ldap_extended_operation( ld,
+ LDAP_EXOP_X_MODIFY_PASSWD, bv,
+ NULL, NULL, &id );
+
+ ber_bvfree( bv );
+
+ if( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_extended_operation" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
+ if ( rc < 0 ) {
+ ldap_perror( ld, "ldappasswd: ldap_result" );
+ return rc;
+ }
+
+ rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 );
+
+ if( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_parse_result" );
+ return rc;
+ }
+
+ rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
+
+ if( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_parse_result" );
+ return rc;
+ }
+
+ if( retdata != NULL ) {
+ ber_tag_t tag;
+ char *s;
+ BerElement *ber = ber_init( retdata );
+
+ if( ber == NULL ) {
+ perror( "ber_init" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ /* we should check the tag */
+ tag = ber_scanf( ber, "{a}", &s);
+
+ if( tag == LBER_ERROR ) {
+ perror( "ber_scanf" );
+ } else {
+ printf("New password: %s\n", s);
+ free( s );
+ }
+
+ ber_free( ber, 1 );
+ }
+
+ if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
+ printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
+
+ if( text && *text ) {
+ printf( "Additional info: %s\n", text );
+ }
+
+ if( matcheddn && *matcheddn ) {
+ printf( "Matched DN: %s\n", matcheddn );
+ }
+
+ if( refs ) {
+ int i;
+ for( i=0; refs[i]; i++ ) {
+ printf("Referral: %s\n", refs[i] );