+ struct berval bv = BER_BVNULL;
+
+ if ( !mi )
+ return 1;
+
+ if ( c->table == Cft_Database ) {
+ mt = NULL;
+ mc = &mi->mi_mc;
+ } else {
+ mt = c->ca_private;
+ mc = &mt->mt_mc;
+ }
+
+ switch( c->type ) {
+ /* Base attrs */
+ case LDAP_BACK_CFG_CONN_TTL:
+ if ( mi->mi_conn_ttl == 0 ) {
+ return 1;
+ } else {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ lutil_unparse_time( buf, sizeof( buf ), mi->mi_conn_ttl );
+ ber_str2bv( buf, 0, 0, &bv );
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case LDAP_BACK_CFG_DNCACHE_TTL:
+ if ( mi->mi_cache.ttl == META_DNCACHE_DISABLED ) {
+ return 1;
+ } else if ( mi->mi_cache.ttl == META_DNCACHE_FOREVER ) {
+ BER_BVSTR( &bv, "forever" );
+ } else {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ lutil_unparse_time( buf, sizeof( buf ), mi->mi_cache.ttl );
+ ber_str2bv( buf, 0, 0, &bv );
+ }
+ value_add_one( &c->rvalue_vals, &bv );
+ break;
+
+ case LDAP_BACK_CFG_IDLE_TIMEOUT:
+ if ( mi->mi_idle_timeout == 0 ) {
+ return 1;
+ } else {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ lutil_unparse_time( buf, sizeof( buf ), mi->mi_idle_timeout );
+ ber_str2bv( buf, 0, 0, &bv );
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case LDAP_BACK_CFG_ONERR:
+ enum_to_verb( onerr_mode, mi->mi_flags & META_BACK_F_ONERR_MASK, &bv );
+ if ( BER_BVISNULL( &bv )) {
+ rc = 1;
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
+ c->value_int = META_BACK_DEFER_ROOTDN_BIND( mi );
+ break;
+
+ case LDAP_BACK_CFG_SINGLECONN:
+ c->value_int = LDAP_BACK_SINGLECONN( mi );
+ break;
+
+ case LDAP_BACK_CFG_USETEMP:
+ c->value_int = LDAP_BACK_USE_TEMPORARIES( mi );
+ break;
+
+ case LDAP_BACK_CFG_CONNPOOLMAX:
+ c->value_int = mi->mi_conn_priv_max;
+ break;
+
+ /* common attrs */
+ case LDAP_BACK_CFG_BIND_TIMEOUT:
+ if ( mc->mc_bind_timeout.tv_sec == 0 &&
+ mc->mc_bind_timeout.tv_usec == 0 ) {
+ return 1;
+ } else {
+ c->value_ulong = mc->mc_bind_timeout.tv_sec * 1000000UL +
+ mc->mc_bind_timeout.tv_usec;
+ }
+ break;
+
+ case LDAP_BACK_CFG_CANCEL: {
+ slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2;
+
+ if ( mt && META_BACK_TGT_CANCEL_DISCOVER( mt ) ) {
+ mask &= ~LDAP_BACK_F_CANCEL_EXOP;
+ }
+ enum_to_verb( cancel_mode, (mc->mc_flags & mask), &bv );
+ if ( BER_BVISNULL( &bv ) ) {
+ /* there's something wrong... */
+ assert( 0 );
+ rc = 1;
+
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ } break;
+
+ case LDAP_BACK_CFG_CHASE:
+ c->value_int = META_BACK_CMN_CHASE_REFERRALS(mc);
+ break;
+
+#ifdef SLAPD_META_CLIENT_PR
+ case LDAP_BACK_CFG_CLIENT_PR:
+ if ( mc->mc_ps == META_CLIENT_PR_DISABLE ) {
+ return 1;
+ } else if ( mc->mc_ps == META_CLIENT_PR_ACCEPT_UNSOLICITED ) {
+ BER_BVSTR( &bv, "accept-unsolicited" );
+ } else {
+ bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mc->mc_ps );
+ bv.bv_val = c->cr_msg;
+ }
+ value_add_one( &c->rvalue_vals, &bv );
+ break;
+#endif /* SLAPD_META_CLIENT_PR */
+
+ case LDAP_BACK_CFG_DEFAULT_T:
+ if ( mt || mi->mi_defaulttarget == META_DEFAULT_TARGET_NONE )
+ return 1;
+ bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mi->mi_defaulttarget );
+ bv.bv_val = c->cr_msg;
+ value_add_one( &c->rvalue_vals, &bv );
+ break;
+
+ case LDAP_BACK_CFG_NETWORK_TIMEOUT:
+ if ( mc->mc_network_timeout == 0 ) {
+ return 1;
+ }
+ bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%ld",
+ mc->mc_network_timeout );
+ bv.bv_val = c->cr_msg;
+ value_add_one( &c->rvalue_vals, &bv );
+ break;
+
+ case LDAP_BACK_CFG_NOREFS:
+ c->value_int = META_BACK_CMN_NOREFS(mc);
+ break;
+
+ case LDAP_BACK_CFG_NOUNDEFFILTER:
+ c->value_int = META_BACK_CMN_NOUNDEFFILTER(mc);
+ break;
+
+ case LDAP_BACK_CFG_NRETRIES:
+ if ( mc->mc_nretries == META_RETRY_FOREVER ) {
+ BER_BVSTR( &bv, "forever" );
+ } else if ( mc->mc_nretries == META_RETRY_NEVER ) {
+ BER_BVSTR( &bv, "never" );
+ } else {
+ bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d",
+ mc->mc_nretries );
+ bv.bv_val = c->cr_msg;
+ }
+ value_add_one( &c->rvalue_vals, &bv );
+ break;
+
+ case LDAP_BACK_CFG_QUARANTINE:
+ if ( !META_BACK_CMN_QUARANTINE( mc )) {
+ rc = 1;
+ break;
+ }
+ rc = mi->mi_ldap_extra->retry_info_unparse( &mc->mc_quarantine, &bv );
+ if ( rc == 0 ) {
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case LDAP_BACK_CFG_REBIND:
+ c->value_int = META_BACK_CMN_SAVECRED(mc);
+ break;
+
+ case LDAP_BACK_CFG_TIMEOUT:
+ for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+ if ( mc->mc_timeout[ i ] != 0 ) {
+ break;
+ }
+ }
+
+ if ( i == SLAP_OP_LAST ) {
+ return 1;
+ }
+
+ BER_BVZERO( &bv );
+ slap_cf_aux_table_unparse( mc->mc_timeout, &bv, timeout_table );
+
+ if ( BER_BVISNULL( &bv ) ) {
+ return 1;
+ }
+
+ for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
+ /* count spaces */ ;
+
+ if ( i ) {
+ bv.bv_len -= i;
+ AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
+ bv.bv_len + 1 );
+ }
+
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ break;
+
+ case LDAP_BACK_CFG_VERSION:
+ if ( mc->mc_version == 0 )
+ return 1;
+ c->value_int = mc->mc_version;
+ break;
+
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+ case LDAP_BACK_CFG_ST_REQUEST:
+ c->value_int = META_BACK_CMN_ST_REQUEST( mc );
+ break;
+#endif /* SLAP_CONTROL_X_SESSION_TRACKING */
+
+ case LDAP_BACK_CFG_T_F:
+ enum_to_verb( t_f_mode, (mc->mc_flags & LDAP_BACK_F_T_F_MASK2), &bv );
+ if ( BER_BVISNULL( &bv ) ) {
+ /* there's something wrong... */
+ assert( 0 );
+ rc = 1;
+
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ break;
+
+ case LDAP_BACK_CFG_TLS: {
+ struct berval bc = BER_BVNULL, bv2;
+
+ if (( mc->mc_flags & LDAP_BACK_F_TLS_MASK ) == LDAP_BACK_F_NONE ) {
+ rc = 1;
+ break;
+ }
+ enum_to_verb( tls_mode, ( mc->mc_flags & LDAP_BACK_F_TLS_MASK ), &bv );
+ assert( !BER_BVISNULL( &bv ) );
+
+ if ( mt ) {
+ bindconf_tls_unparse( &mt->mt_tls, &bc );
+ }
+
+ if ( !BER_BVISEMPTY( &bc )) {
+ bv2.bv_len = bv.bv_len + bc.bv_len + 1;
+ bv2.bv_val = ch_malloc( bv2.bv_len + 1 );
+ strcpy( bv2.bv_val, bv.bv_val );
+ bv2.bv_val[bv.bv_len] = ' ';
+ strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val );
+ ber_memfree( bc.bv_val );
+ ber_bvarray_add( &c->rvalue_vals, &bv2 );
+ } else {
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ } break;
+
+ /* target attrs */
+ case LDAP_BACK_CFG_URI: {
+ char *p2, *p1 = strchr( mt->mt_uri, ' ' );
+ bv.bv_len = strlen( mt->mt_uri ) + 1 + mt->mt_psuffix.bv_len;
+ bv.bv_val = ch_malloc( bv.bv_len + 1 );
+ if ( p1 ) {
+ p2 = lutil_strncopy( bv.bv_val, mt->mt_uri, p1 - mt->mt_uri );
+ } else {
+ p2 = lutil_strcopy( bv.bv_val, mt->mt_uri );
+ }
+ *p2++ = '/';
+ p2 = lutil_strcopy( p2, mt->mt_psuffix.bv_val );
+ if ( p1 ) {
+ strcpy( p2, p1 );
+ }
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ } break;
+
+ case LDAP_BACK_CFG_ACL_AUTHCDN:
+ case LDAP_BACK_CFG_ACL_PASSWD:
+ /* FIXME no point here, there is no code implementing
+ * their features. Was this supposed to implement
+ * acl-bind like back-ldap?
+ */
+ rc = 1;
+ break;
+
+ case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
+ BerVarray *bvp;
+ int i;
+ struct berval bv = BER_BVNULL;
+ char buf[SLAP_TEXT_BUFLEN];
+
+ bvp = &mt->mt_idassert_authz;
+ if ( *bvp == NULL ) {
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL )
+ {
+ BER_BVSTR( &bv, "*" );
+ value_add_one( &c->rvalue_vals, &bv );
+
+ } else {
+ rc = 1;
+ }
+ break;
+ }
+
+ for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) {
+ char *ptr;
+ int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
+ bv.bv_len = ((*bvp)[ i ]).bv_len + len;
+ bv.bv_val = ber_memrealloc( bv.bv_val, bv.bv_len + 1 );
+ ptr = bv.bv_val;
+ ptr = lutil_strcopy( ptr, buf );
+ ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len );
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ if ( bv.bv_val ) {
+ ber_memfree( bv.bv_val );
+ }
+ break;
+ }
+
+ case LDAP_BACK_CFG_IDASSERT_BIND: {
+ int i;
+ struct berval bc = BER_BVNULL;
+ char *ptr;
+
+ if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) {
+ return 1;
+ } else {
+ ber_len_t len;
+
+ switch ( mt->mt_idassert_mode ) {
+ case LDAP_BACK_IDASSERT_OTHERID:
+ case LDAP_BACK_IDASSERT_OTHERDN:
+ break;
+
+ default: {
+ struct berval mode = BER_BVNULL;
+
+ enum_to_verb( idassert_mode, mt->mt_idassert_mode, &mode );
+ if ( BER_BVISNULL( &mode ) ) {
+ /* there's something wrong... */
+ assert( 0 );
+ rc = 1;
+
+ } else {
+ bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
+ bv.bv_val = ch_malloc( bv.bv_len + 1 );
+
+ ptr = lutil_strcopy( bv.bv_val, "mode=" );
+ ptr = lutil_strcopy( ptr, mode.bv_val );
+ }
+ break;
+ }
+ }
+
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
+ len = bv.bv_len + STRLENOF( "authz=native" );
+
+ if ( !BER_BVISEMPTY( &bv ) ) {
+ len += STRLENOF( " " );
+ }
+
+ bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
+
+ ptr = &bv.bv_val[ bv.bv_len ];
+
+ if ( !BER_BVISEMPTY( &bv ) ) {
+ ptr = lutil_strcopy( ptr, " " );
+ }
+
+ (void)lutil_strcopy( ptr, "authz=native" );
+ }
+
+ len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" );
+ /* flags */
+ if ( !BER_BVISEMPTY( &bv ) ) {
+ len += STRLENOF( " " );
+ }
+
+ bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
+
+ ptr = &bv.bv_val[ bv.bv_len ];
+
+ if ( !BER_BVISEMPTY( &bv ) ) {
+ ptr = lutil_strcopy( ptr, " " );
+ }
+
+ ptr = lutil_strcopy( ptr, "flags=" );
+
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+ ptr = lutil_strcopy( ptr, "prescriptive" );
+ } else {
+ ptr = lutil_strcopy( ptr, "non-prescriptive" );
+ }
+
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
+ ptr = lutil_strcopy( ptr, ",override" );
+ }
+
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+ ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
+
+ } else if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+ ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
+ }
+
+ if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) {
+ ptr = lutil_strcopy( ptr, ",proxy-authz-critical" );
+
+ } else {
+ ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" );
+ }
+
+#ifdef SLAP_AUTH_DN
+ switch ( mt->mt_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) {
+ case LDAP_BACK_AUTH_DN_AUTHZID:
+ ptr = lutil_strcopy( ptr, ",dn-authzid" );
+ break;
+
+ case LDAP_BACK_AUTH_DN_WHOAMI:
+ ptr = lutil_strcopy( ptr, ",dn-whoami" );
+ break;
+
+ default:
+#if 0 /* implicit */
+ ptr = lutil_strcopy( ptr, ",dn-none" );
+#endif
+ break;
+ }
+#endif
+
+ bv.bv_len = ( ptr - bv.bv_val );
+ /* end-of-flags */
+ }
+
+ bindconf_unparse( &mt->mt_idassert.si_bc, &bc );
+
+ if ( !BER_BVISNULL( &bv ) ) {
+ ber_len_t len = bv.bv_len + bc.bv_len;
+
+ bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
+
+ assert( bc.bv_val[ 0 ] == ' ' );
+
+ ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
+ free( bc.bv_val );
+ bv.bv_len = ptr - bv.bv_val;
+
+ } else {
+ for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
+ /* count spaces */ ;
+
+ if ( i ) {
+ bc.bv_len -= i;
+ AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
+ }
+
+ bv = bc;
+ }
+
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+
+ break;
+ }
+
+ case LDAP_BACK_CFG_SUFFIXM: /* unused */
+ case LDAP_BACK_CFG_REWRITE:
+ if ( mt->mt_rwmap.rwm_bva_rewrite == NULL ) {
+ rc = 1;
+ } else {
+ rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_rewrite, &c->rvalue_vals );
+ }
+ break;
+
+ case LDAP_BACK_CFG_MAP:
+ if ( mt->mt_rwmap.rwm_bva_map == NULL ) {
+ rc = 1;
+ } else {
+ rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_map, &c->rvalue_vals );
+ }
+ break;
+
+ case LDAP_BACK_CFG_SUBTREE_EX:
+ case LDAP_BACK_CFG_SUBTREE_IN:
+ rc = meta_subtree_unparse( c, mt );
+ break;
+
+ /* replaced by idassert */
+ case LDAP_BACK_CFG_PSEUDOROOTDN:
+ case LDAP_BACK_CFG_PSEUDOROOTPW:
+ rc = 1;
+ break;
+
+ default:
+ rc = 1;
+ }
+ return rc;