Example #1
0
int
shell_back_unbind(
    Operation		*op,
    SlapReply		*rs
)
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	FILE			*rfp, *wfp;

	if ( si->si_unbind == NULL ) {
		return 0;
	}

	if ( forkandexec( si->si_unbind, &rfp, &wfp ) == (pid_t)-1 ) {
		return 0;
	}

	/* write out the request to the unbind process */
	fprintf( wfp, "UNBIND\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "dn: %s\n", (op->o_conn->c_dn.bv_len ? op->o_conn->c_dn.bv_val : "") );
	fclose( wfp );

	/* no response to unbind */
	fclose( rfp );

	return 0;
}
Example #2
0
int
shell_back_compare(
    Operation	*op,
    SlapReply	*rs )
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	Entry e;
	FILE			*rfp, *wfp;

	if ( si->si_compare == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "compare not implemented" );
		return( -1 );
	}

	e.e_id = NOID;
	e.e_name = op->o_req_dn;
	e.e_nname = op->o_req_ndn;
	e.e_attrs = NULL;
	e.e_ocflags = 0;
	e.e_bv.bv_len = 0;
	e.e_bv.bv_val = NULL;
	e.e_private = NULL;

	if ( ! access_allowed( op, &e,
		entry, NULL, ACL_READ, NULL ) )
	{
		send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
		return -1;
	}

	if ( forkandexec( si->si_compare, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/*
	 * FIX ME:  This should use LDIF routines so that binary
	 *	values are properly dealt with
	 */

	/* write out the request to the compare process */
	fprintf( wfp, "COMPARE\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
	fprintf( wfp, "%s: %s\n",
		op->oq_compare.rs_ava->aa_desc->ad_cname.bv_val,
		op->oq_compare.rs_ava->aa_value.bv_val /* could be binary! */ );
	fclose( wfp );

	/* read in the result and send it along */
	read_and_send_results( op, rs, rfp );

	fclose( rfp );
	return( 0 );
}
Example #3
0
int
shell_back_search(
    Backend	*be,
    Connection	*conn,
    Operation	*op,
    struct berval *base,
    struct berval *nbase,
    int		scope,
    int		deref,
    int		size,
    int		time,
    Filter	*filter,
    struct berval	*filterstr,
    AttributeName	*attrs,
    int		attrsonly
)
{
	struct shellinfo	*si = (struct shellinfo *) be->be_private;
	FILE			*rfp, *wfp;
	AttributeName		*an;

	if ( si->si_search == NULL ) {
		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
		    "search not implemented", NULL, NULL );
		return( -1 );
	}

	if ( (op->o_private = (void *) forkandexec( si->si_search, &rfp, &wfp ))
	    == (void *) -1 ) {
		send_ldap_result( conn, op, LDAP_OTHER, NULL,
		    "could not fork/exec", NULL, NULL );
		return( -1 );
	}

	/* write out the request to the search process */
	fprintf( wfp, "SEARCH\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, be );
	fprintf( wfp, "base: %s\n", base->bv_val );
	fprintf( wfp, "scope: %d\n", scope );
	fprintf( wfp, "deref: %d\n", deref );
	fprintf( wfp, "sizelimit: %d\n", size );
	fprintf( wfp, "timelimit: %d\n", time );
	fprintf( wfp, "filter: %s\n", filterstr->bv_val );
	fprintf( wfp, "attrsonly: %d\n", attrsonly ? 1 : 0 );
	fprintf( wfp, "attrs:%s", attrs == NULL ? " all" : "" );
	for ( an = attrs; an && an->an_name.bv_val; an++ ) {
		fprintf( wfp, " %s", an->an_name.bv_val );
	}
	fprintf( wfp, "\n" );
	fclose( wfp );

	/* read in the results and send them along */
	read_and_send_results( be, conn, op, rfp, attrs, attrsonly );

	fclose( rfp );
	return( 0 );
}
Example #4
0
int
shell_back_modrdn(
    Operation	*op,
    SlapReply	*rs )
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	Entry e;
	FILE			*rfp, *wfp;

	if ( si->si_modrdn == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "modrdn not implemented" );
		return( -1 );
	}

	e.e_id = NOID;
	e.e_name = op->o_req_dn;
	e.e_nname = op->o_req_ndn;
	e.e_attrs = NULL;
	e.e_ocflags = 0;
	e.e_bv.bv_len = 0;
	e.e_bv.bv_val = NULL;
	e.e_private = NULL;

	if ( ! access_allowed( op, &e, entry, NULL,
			op->oq_modrdn.rs_newSup ? ACL_WDEL : ACL_WRITE,
			NULL ) )
	{
		send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
		return -1;
	}

	if ( forkandexec( si->si_modrdn, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/* write out the request to the modrdn process */
	fprintf( wfp, "MODRDN\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
	fprintf( wfp, "newrdn: %s\n", op->oq_modrdn.rs_newrdn.bv_val );
	fprintf( wfp, "deleteoldrdn: %d\n", op->oq_modrdn.rs_deleteoldrdn ? 1 : 0 );
	if ( op->oq_modrdn.rs_newSup != NULL ) {
		fprintf( wfp, "newSuperior: %s\n", op->oq_modrdn.rs_newSup->bv_val );
	}
	fclose( wfp );

	/* read in the results and send them along */
	read_and_send_results( op, rs, rfp );
	fclose( rfp );
	return( 0 );
}
Example #5
0
int
shell_back_search(
    Operation	*op,
    SlapReply	*rs )
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	FILE			*rfp, *wfp;
	AttributeName		*an;

	if ( si->si_search == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "search not implemented" );
		return( -1 );
	}

	if ( forkandexec( si->si_search, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/* write out the request to the search process */
	fprintf( wfp, "SEARCH\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "base: %s\n", op->o_req_dn.bv_val );
	fprintf( wfp, "scope: %d\n", op->oq_search.rs_scope );
	fprintf( wfp, "deref: %d\n", op->oq_search.rs_deref );
	fprintf( wfp, "sizelimit: %d\n", op->oq_search.rs_slimit );
	fprintf( wfp, "timelimit: %d\n", op->oq_search.rs_tlimit );
	fprintf( wfp, "filter: %s\n", op->oq_search.rs_filterstr.bv_val );
	fprintf( wfp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 );
	fprintf( wfp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : "" );
	for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) {
		fprintf( wfp, " %s", an->an_name.bv_val );
	}
	fprintf( wfp, "\n" );
	fclose( wfp );

	/* read in the results and send them along */
	rs->sr_attrs = op->oq_search.rs_attrs;
	read_and_send_results( op, rs, rfp );

	fclose( rfp );
	return( 0 );
}
Example #6
0
int
shell_back_add(
    Operation	*op,
    SlapReply	*rs )
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	FILE			*rfp, *wfp;
	int			len;

	if ( si->si_add == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "add not implemented" );
		return( -1 );
	}

	if ( ! access_allowed( op, op->oq_add.rs_e,
		entry, NULL, ACL_WADD, NULL ) )
	{
		send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
		return -1;
	}

	if ( forkandexec( si->si_add, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/* write out the request to the add process */
	fprintf( wfp, "ADD\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	ldap_pvt_thread_mutex_lock( &entry2str_mutex );
	fprintf( wfp, "%s", entry2str( op->oq_add.rs_e, &len ) );
	ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
	fclose( wfp );

	/* read in the result and send it along */
	read_and_send_results( op, rs, rfp );

	fclose( rfp );
	return( 0 );
}
Example #7
0
int
shell_back_bind(
    Operation		*op,
    SlapReply		*rs )
{
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	Entry e;
	FILE			*rfp, *wfp;
	int			rc;

	/* allow rootdn as a means to auth without the need to actually
 	 * contact the proxied DSA */
	switch ( be_rootdn_bind( op, rs ) ) {
	case SLAP_CB_CONTINUE:
		break;

	default:
		return rs->sr_err;
	}

	if ( si->si_bind == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "bind not implemented" );
		return( -1 );
	}

	e.e_id = NOID;
	e.e_name = op->o_req_dn;
	e.e_nname = op->o_req_ndn;
	e.e_attrs = NULL;
	e.e_ocflags = 0;
	e.e_bv.bv_len = 0;
	e.e_bv.bv_val = NULL;
	e.e_private = NULL;

	if ( ! access_allowed( op, &e,
		entry, NULL, ACL_AUTH, NULL ) )
	{
		send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
		return -1;
	}

	if ( forkandexec( si->si_bind, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/* write out the request to the bind process */
	fprintf( wfp, "BIND\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
	fprintf( wfp, "method: %d\n", op->oq_bind.rb_method );
	fprintf( wfp, "credlen: %lu\n", op->oq_bind.rb_cred.bv_len );
	fprintf( wfp, "cred: %s\n", op->oq_bind.rb_cred.bv_val ); /* XXX */
	fclose( wfp );

	/* read in the results and send them along */
	rc = read_and_send_results( op, rs, rfp );
	fclose( rfp );

	return( rc );
}
Example #8
0
int
shell_back_modify(
    Operation	*op,
    SlapReply	*rs )
{
	Modification *mod;
	struct shellinfo	*si = (struct shellinfo *) op->o_bd->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	Modifications *ml  = op->orm_modlist;
	Entry e;
	FILE			*rfp, *wfp;
	int			i;

	if ( si->si_modify == NULL ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "modify not implemented" );
		return( -1 );
	}

	e.e_id = NOID;
	e.e_name = op->o_req_dn;
	e.e_nname = op->o_req_ndn;
	e.e_attrs = NULL;
	e.e_ocflags = 0;
	e.e_bv.bv_len = 0;
	e.e_bv.bv_val = NULL;
	e.e_private = NULL;

	if ( ! access_allowed( op, &e,
		entry, NULL, ACL_WRITE, NULL ) )
	{
		send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
		return -1;
	}

	if ( forkandexec( si->si_modify, &rfp, &wfp ) == (pid_t)-1 ) {
		send_ldap_error( op, rs, LDAP_OTHER,
		    "could not fork/exec" );
		return( -1 );
	}

	/* write out the request to the modify process */
	fprintf( wfp, "MODIFY\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, op->o_bd );
	fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
	for ( ; ml != NULL; ml = ml->sml_next ) {
		mod = &ml->sml_mod;

		switch ( mod->sm_op ) {
		case LDAP_MOD_ADD:
			fprintf( wfp, "add: %s\n", mod->sm_desc->ad_cname.bv_val );
			break;

		case LDAP_MOD_DELETE:
			fprintf( wfp, "delete: %s\n", mod->sm_desc->ad_cname.bv_val );
			break;

		case LDAP_MOD_REPLACE:
			fprintf( wfp, "replace: %s\n", mod->sm_desc->ad_cname.bv_val );
			break;
		}

		if( mod->sm_values != NULL ) {
			for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
				char *out = ldif_put( LDIF_PUT_VALUE,
					mod->sm_desc->ad_cname.bv_val,
					mod->sm_values[i].bv_val,
					mod->sm_values[i].bv_len );
				if ( out ) {
					fprintf( wfp, "%s", out );
					ber_memfree( out );
				}
			}
		}

		fprintf( wfp, "-\n" );
	}
	fclose( wfp );

	/* read in the results and send them along */
	read_and_send_results( op, rs, rfp );
	fclose( rfp );
	return( 0 );
}
Example #9
0
/*
 * Validate the pending changes in the e entry.
 * If returntext is NULL, we log messages about invalid config
 * to the errors log.
 */
int 
pam_passthru_validate_config (Slapi_Entry* e, char *returntext)
{
	int rc = PAM_PASSTHRU_FAILURE;
	char *missing_suffix_str = NULL;
	int missing_suffix;
	int ii;
	char **excludes = NULL;
	char **includes = NULL;
	char *pam_ident_attr = NULL;
	char *map_method = NULL;
	char *pam_filter_str = NULL;
	Slapi_Filter *pam_filter = NULL;

	/* first, get the missing_suffix flag and validate it */
	missing_suffix_str = slapi_entry_attr_get_charptr(e, PAMPT_MISSING_SUFFIX_ATTR);
	if ((missing_suffix = missing_suffix_to_int(missing_suffix_str)) < 0 ||
		!check_missing_suffix_flag(missing_suffix)) {
		if (returntext) {
			PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
					"Error: valid values for %s are %s",
					PAMPT_MISSING_SUFFIX_ATTR, get_missing_suffix_values());
		} else {
			slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
					"pam_passthru_validate_config - Valid values for %s are %s\n",
					PAMPT_MISSING_SUFFIX_ATTR, get_missing_suffix_values());
		}
		goto done;
	}

	if (missing_suffix != PAMPT_MISSING_SUFFIX_IGNORE) {
		char **missing_list = NULL;

		/* get the list of excluded suffixes */
		excludes = slapi_entry_attr_get_charray(e, PAMPT_EXCLUDES_ATTR);
		for (ii = 0; excludes && excludes[ii]; ++ii) {
			/* The excludes DNs are already normalized. */
			Slapi_DN *comp_dn = slapi_sdn_new_normdn_byref(excludes[ii]);
			if (!slapi_be_exist(comp_dn)) {
				charray_add(&missing_list, slapi_ch_strdup(excludes[ii]));
			}
			slapi_sdn_free(&comp_dn);
		}

		/* get the list of included suffixes */
		includes = slapi_entry_attr_get_charray(e, PAMPT_INCLUDES_ATTR);
		for (ii = 0; includes && includes[ii]; ++ii) {
			/* The includes DNs are already normalized. */
			Slapi_DN *comp_dn = slapi_sdn_new_normdn_byref(includes[ii]);
			if (!slapi_be_exist(comp_dn)) {
				charray_add(&missing_list, slapi_ch_strdup(includes[ii]));
			}
			slapi_sdn_free(&comp_dn);
		}

		if (missing_list) {
			if (returntext) {
				PRUint32 size =
					PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
								"The following suffixes listed in %s or %s are not present in this "
								"server: ", PAMPT_EXCLUDES_ATTR, PAMPT_INCLUDES_ATTR);
				for (ii = 0; missing_list[ii]; ++ii) {
					if (size < SLAPI_DSE_RETURNTEXT_SIZE) {
						size += PR_snprintf(returntext+size, SLAPI_DSE_RETURNTEXT_SIZE-size,
											"%s%s", (ii > 0) ? "; " : "",
											missing_list[ii]);
					}
				}
			} else {
				slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
							"pam_passthru_validate_config - The suffixes listed in %s or %s are not present in "
							"this server\n", PAMPT_EXCLUDES_ATTR, PAMPT_INCLUDES_ATTR);
			}

			slapi_ch_array_free(missing_list);
			missing_list = NULL;
			print_suffixes();
			if (missing_suffix != PAMPT_MISSING_SUFFIX_ERROR) {
				if (returntext) {
					slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
									"pam_passthru_validate_config - Warning: %s\n", returntext);
					*returntext = 0; /* log error, don't report back to user */
				}
			} else {
				goto done;
			}
		}
	}

	pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR);
	map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR);
	if (map_method) {
		int one, two, three;
		if (PAM_PASSTHRU_SUCCESS !=
			(rc = parse_map_method(map_method, &one, &two, &three, returntext))) {
			goto done; /* returntext set already (or error logged) */
		}
		if (!pam_ident_attr &&
			((one == PAMPT_MAP_METHOD_ENTRY) || (two == PAMPT_MAP_METHOD_ENTRY) ||
			 (three == PAMPT_MAP_METHOD_ENTRY))) {
			if (returntext) {
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: the %s method"
							" was specified, but no %s was given",
							PAMPT_MAP_METHOD_ENTRY_STRING, PAMPT_PAM_IDENT_ATTR);
			} else {
				slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
							"pam_passthru_validate_config - The %s method was specified, but no %s was given\n",
							PAMPT_MAP_METHOD_ENTRY_STRING, PAMPT_PAM_IDENT_ATTR);
			}
			rc = PAM_PASSTHRU_FAILURE;
			goto done;
		}
		if ((one == PAMPT_MAP_METHOD_NONE) && (two == PAMPT_MAP_METHOD_NONE) &&
			(three == PAMPT_MAP_METHOD_NONE)) {
			if (returntext) {
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no method(s)"
							" specified for %s, should be one or more of %s",
							PAMPT_MAP_METHOD_ATTR, get_map_method_values());
			} else {
				slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
							"pam_passthru_validate_config - No method(s) specified for %s, should be "
							"one or more of %s\n", PAMPT_MAP_METHOD_ATTR,
							get_map_method_values());
			}
			rc = PAM_PASSTHRU_FAILURE;
			goto done;
		}
	}

	/* Validate filter by converting to Slapi_Filter */
	pam_filter_str = slapi_entry_attr_get_charptr(e, PAMPT_FILTER_ATTR);
	if (pam_filter_str) {
		pam_filter = slapi_str2filter(pam_filter_str);
		if (pam_filter == NULL) {
			if (returntext) {
				PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: invalid "
							"filter specified for %s (filter: \"%s\")",
							PAMPT_FILTER_ATTR, pam_filter_str);
			} else {
				slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
							"pam_passthru_validate_config - Invalid filter specified for %s "
							"(filter: \"%s\")\n", PAMPT_FILTER_ATTR,
							pam_filter_str);
			}
			rc = PAM_PASSTHRU_FAILURE;
			goto done;
		}
	}

	/* success */
	rc = PAM_PASSTHRU_SUCCESS;

done:
	slapi_ch_free_string(&map_method);
	slapi_ch_free_string(&pam_ident_attr);
	slapi_ch_array_free(excludes);
	excludes = NULL;
	slapi_ch_array_free(includes);
	includes = NULL;
	slapi_ch_free_string(&missing_suffix_str);
	slapi_ch_free_string(&pam_filter_str);
	slapi_filter_free(pam_filter, 1);

	return rc;
}
Example #10
0
int
shell_back_bind(
    Backend		*be,
    Connection		*conn,
    Operation		*op,
    struct berval	*dn,
    struct berval	*ndn,
    int			method,
    struct berval	*cred,
    struct berval	*edn
)
{
	struct shellinfo	*si = (struct shellinfo *) be->be_private;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	Entry e;
	FILE			*rfp, *wfp;
	int			rc;

	if ( si->si_bind == NULL ) {
		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
		    "bind not implemented", NULL, NULL );
		return( -1 );
	}

	e.e_id = NOID;
	e.e_name = *dn;
	e.e_nname = *ndn;
	e.e_attrs = NULL;
	e.e_ocflags = 0;
	e.e_bv.bv_len = 0;
	e.e_bv.bv_val = NULL;
	e.e_private = NULL;

	if ( ! access_allowed( be, conn, op, &e,
		entry, NULL, ACL_AUTH, NULL ) )
	{
		send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
			NULL, NULL, NULL, NULL );
		return -1;
	}

	if ( (op->o_private = (void *) forkandexec( si->si_bind, &rfp, &wfp ))
	    == (void *) -1 ) {
		send_ldap_result( conn, op, LDAP_OTHER, NULL,
		    "could not fork/exec", NULL, NULL );
		return( -1 );
	}

	/* write out the request to the bind process */
	fprintf( wfp, "BIND\n" );
	fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
	print_suffixes( wfp, be );
	fprintf( wfp, "dn: %s\n", dn->bv_val );
	fprintf( wfp, "method: %d\n", method );
	fprintf( wfp, "credlen: %lu\n", cred->bv_len );
	fprintf( wfp, "cred: %s\n", cred->bv_val ); /* XXX */
	fclose( wfp );

	/* read in the results and send them along */
	rc = read_and_send_results( be, conn, op, rfp, NULL, 0 );
	fclose( rfp );

	return( rc );
}