Пример #1
0
/* Called when results come in for a key send */
static gboolean
on_import_add_completed (LDAPMessage *result,
                         gpointer user_data)
{
	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
	source_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data));
	GError *error = NULL;
	char *message;
	int code;
	int rc;

	g_return_val_if_fail (ldap_msgtype (result) == LDAP_RES_ADD, FALSE);

	rc = ldap_parse_result (closure->ldap, result, &code, NULL,
	                        &message, NULL, NULL, 0);
	g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);

	/* TODO: Somehow communicate this to the user */
	if (code == LDAP_ALREADY_EXISTS)
		code = LDAP_SUCCESS;

	ldap_memfree (message);

	if (seahorse_ldap_source_propagate_error (self, code, &error)) {
		g_simple_async_result_take_error (res, error);
		g_simple_async_result_complete (res);
		return FALSE; /* don't call for this source again */
	}

	import_send_key (self, res);
	return FALSE; /* don't call for this source again */
}
Пример #2
0
static gboolean
on_connect_bind_completed (LDAPMessage *result,
                           gpointer user_data)
{
	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
	source_connect_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data));
	LDAPServerInfo *sinfo;
	GError *error = NULL;
	char *message;
	int ldap_op;
	int code;
	int rc;

	g_return_val_if_fail (ldap_msgtype (result) == LDAP_RES_BIND, FALSE);

	/* The result of the bind operation */
	rc = ldap_parse_result (closure->ldap, result, &code, NULL, &message, NULL, NULL, 0);
	g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);
	ldap_memfree (message);

	if (seahorse_ldap_source_propagate_error (self, rc, &error)) {
		g_simple_async_result_take_error (res, error);
		g_simple_async_result_complete_in_idle (res);
		return FALSE; /* don't call this callback again */
	}

	/* Check if we need server info */
	sinfo = get_ldap_server_info (self, FALSE);
	if (sinfo != NULL) {
		g_simple_async_result_complete_in_idle (res);
		seahorse_progress_end (closure->cancellable, res);
		return FALSE; /* don't call this callback again */
	}

	/* Retrieve the server info */
	rc = ldap_search_ext (closure->ldap, "cn=PGPServerInfo", LDAP_SCOPE_BASE,
	                      "(objectclass=*)", (char **)SERVER_ATTRIBUTES, 0,
	                      NULL, NULL, NULL, 0, &ldap_op);

	if (seahorse_ldap_source_propagate_error (self, rc, &error)) {
		g_simple_async_result_take_error (res, error);
		g_simple_async_result_complete_in_idle (res);
		return FALSE; /* don't call this callback again */

	} else {
		GSource *gsource = seahorse_ldap_gsource_new (closure->ldap, ldap_op,
		                                              closure->cancellable);
		g_source_set_callback (gsource, (GSourceFunc)on_connect_server_info_completed,
		                       g_object_ref (res), g_object_unref);
		g_source_attach (gsource, g_main_context_default ());
		g_source_unref (gsource);
	}

	return FALSE; /* don't call this callback again */
}
Пример #3
0
/* Iterate to the next search result in the linked list
 * of messages returned by the LDAP server and convert
 * the field values.
 */
static int search_entry(db_res_t* res, int init)
{
	db_con_t* con;
	struct ld_res* lres;
	struct ld_con* lcon;
	int r;
	lres = DB_GET_PAYLOAD(res);
	/* FIXME */
	con = res->cmd->ctx->con[db_payload_idx];
	lcon = DB_GET_PAYLOAD(con);

	if (init
	    || !lres->current
	    || ldap_msgtype(lres->current) != LDAP_RES_SEARCH_ENTRY
	    /* there is no more value combination result left */
	    || ld_incindex(res->cmd->result)) {

		do {
			if (init) {
				lres->current = ldap_first_message(lcon->con, lres->msg);
				init = 0;
			}
			else
				lres->current = ldap_next_message(lcon->con, lres->current);
			
			while(lres->current) {
				if (ldap_msgtype(lres->current) == LDAP_RES_SEARCH_ENTRY) {
					break;
				}
				lres->current = ldap_next_message(lcon->con, lres->current);
			}
			if (lres->current == NULL) return 1;
			r = ld_ldap2fldinit(res->cmd->result, lcon->con, lres->current);
		} while (r > 0);
		if (r < 0) return -1;
	} else {
		if (ld_ldap2fld(res->cmd->result, lcon->con, lres->current) < 0) return -1;
	}

	res->cur_rec->fld = res->cmd->result;
	return 0;
}
Пример #4
0
/*
** Retrieve next message...
** @return #1 entry's distinguished name.
** @return #2 table with entry's attributes and values.
*/
static int next_message (lua_State *L) {
	search_data *search = getsearch (L);
	conn_data *conn;
	struct timeval *timeout = NULL; /* ??? function parameter ??? */
	LDAPMessage *res;
	int rc;
	int ret;

	lua_rawgeti (L, LUA_REGISTRYINDEX, search->conn);
	conn = (conn_data *)lua_touserdata (L, -1); /* get connection */

	rc = ldap_result (conn->ld, search->msgid, LDAP_MSG_ONE, timeout, &res);
	if (rc == 0)
		return faildirect (L, LUALDAP_PREFIX"result timeout expired");
	else if (rc == -1)
		return faildirect (L, LUALDAP_PREFIX"result error");
	else if (rc == LDAP_RES_SEARCH_RESULT) { /* last message => nil */
		/* close search object to avoid reuse */
		search_close (L, search);
		ret = 0;
	} else {
		LDAPMessage *msg = ldap_first_message (conn->ld, res);
		switch (ldap_msgtype (msg)) {
			case LDAP_RES_SEARCH_ENTRY: {
				LDAPMessage *entry = ldap_first_entry (conn->ld, msg);
				push_dn (L, conn->ld, entry);
				lua_newtable (L);
				set_attribs (L, conn->ld, entry, lua_gettop (L));
				ret = 2; /* two return values */
				break;
			}
/*No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe there is a replacement to it?*/
#ifdef LDAP_RES_SEARCH_REFERENCE
			case LDAP_RES_SEARCH_REFERENCE: {
				LDAPMessage *ref = ldap_first_reference (conn->ld, msg);
				push_dn (L, conn->ld, ref); /* is this supposed to work? */
				lua_pushnil (L);
				ret = 2; /* two return values */
				break;
			}
#endif
			case LDAP_RES_SEARCH_RESULT:
				/* close search object to avoid reuse */
				search_close (L, search);
				ret = 0;
				break;
			default:
				ldap_msgfree (res);
				return luaL_error (L, LUALDAP_PREFIX"error on search result chain");
		}
	}
	ldap_msgfree (res);
	return ret;
}
Пример #5
0
static int search_iterator(lua_State *L)
{
  LDAPMessage *result, *message, *entry;
  lua_apr_ldap_object *object;
  struct timeval *timeout;
  int status, msgid;

  object = lua_touserdata(L, lua_upvalueindex(1));
  msgid = lua_tointeger(L, lua_upvalueindex(2));
  timeout = lua_touserdata(L, lua_upvalueindex(3));
  status = ldap_result(object->ldap, msgid, LDAP_MSG_ONE, timeout, &result);

  if (status == 0)
    raise_error_status(L, APR_TIMEUP);
  else if (status == -1)
    /* TODO Can we get a more specific error (message) here? ld_errno? */
    raise_error_message(L, "Unspecified error");
  else if (status == LDAP_RES_SEARCH_RESULT) {
    /* end of search results */
    return 0;
  } else {
    message = ldap_first_message(object->ldap, result);
    switch (ldap_msgtype(message)) {
      case LDAP_RES_SEARCH_ENTRY:
        entry = ldap_first_entry(object->ldap, message);
        push_distinguished_name(L, object->ldap, entry);
        lua_newtable(L);
        set_attributes(L, object->ldap, entry, lua_gettop(L));
        ldap_msgfree(result);
        return 2;
      /* No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe is has a replacement? */
#     ifdef LDAP_RES_SEARCH_REFERENCE
      case LDAP_RES_SEARCH_REFERENCE: {
        LDAPMessage *reference = ldap_first_reference(object->ldap, message);
        push_distinguished_name(L, object->ldap, reference); /* is this supposed to work? */
        ldap_msgfree(result);
        return 1;
      }
#     endif
      case LDAP_RES_SEARCH_RESULT:
        /* end of search results */
        ldap_msgfree(result);
        return 0;
      default:
        ldap_msgfree(result);
        raise_error_message(L, "unhandled message type in search results");
    }
  }

  /* shouldn't be reached. */
  ldap_msgfree(result);
  return 0;
}
Пример #6
0
static gboolean
on_search_search_completed (LDAPMessage *result,
                            gpointer user_data)
{
	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
	source_search_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data));
	GError *error = NULL;
	char *message;
	int code;
	int type;
	int rc;

	type = ldap_msgtype (result);
	g_return_val_if_fail (type == LDAP_RES_SEARCH_ENTRY || type == LDAP_RES_SEARCH_RESULT, FALSE);

	/* An LDAP entry */
	if (type == LDAP_RES_SEARCH_ENTRY) {
		g_debug ("Retrieved Key Entry");
#ifdef WITH_DEBUG
		dump_ldap_entry (closure->ldap, result);
#endif

		search_parse_key_from_ldap_entry (self, closure->results,
		                                  closure->ldap, result);
		return TRUE; /* keep calling this callback */

	/* All entries done */
	} else {
		rc = ldap_parse_result (closure->ldap, result, &code, NULL,
		                        &message, NULL, NULL, 0);
		g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);

		/* Error codes that we ignore */
		switch (code) {
		case LDAP_SIZELIMIT_EXCEEDED:
			code = LDAP_SUCCESS;
			break;
		};

		/* Failure */
		if (code != LDAP_SUCCESS)
			g_simple_async_result_set_error (res, LDAP_ERROR_DOMAIN,
			                                 code, "%s", message);
		else if (seahorse_ldap_source_propagate_error (self, code, &error))
			g_simple_async_result_take_error (res, error);

		ldap_memfree (message);
		seahorse_progress_end (closure->cancellable, res);
		g_simple_async_result_complete (res);
		return FALSE;
	}
}
Пример #7
0
static gboolean
on_connect_server_info_completed (LDAPMessage *result,
                                  gpointer user_data)
{
	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
	source_connect_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data));
	LDAPServerInfo *sinfo;
	char *message;
	int code;
	int type;
	int rc;

	type = ldap_msgtype (result);
	g_return_val_if_fail (type == LDAP_RES_SEARCH_ENTRY || type == LDAP_RES_SEARCH_RESULT, FALSE);

	/* If we have results then fill in the server info */
	if (type == LDAP_RES_SEARCH_ENTRY) {

		g_debug ("Server Info Result");
#ifdef WITH_DEBUG
		dump_ldap_entry (closure->ldap, result);
#endif

		/* NOTE: When adding attributes here make sure to add them to kServerAttributes */
		sinfo = g_new0 (LDAPServerInfo, 1);
		sinfo->version = get_int_attribute (closure->ldap, result, "version");
		sinfo->base_dn = get_string_attribute (closure->ldap, result, "basekeyspacedn");
		if (!sinfo->base_dn)
			sinfo->base_dn = get_string_attribute (closure->ldap, result, "pgpbasekeyspacedn");
		sinfo->key_attr = g_strdup (sinfo->version > 1 ? "pgpkeyv2" : "pgpkey");
		set_ldap_server_info (self, sinfo);

		return TRUE; /* callback again */

	} else {
		rc = ldap_parse_result (closure->ldap, result, &code, NULL,
		                        &message, NULL, NULL, 0);
		g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE);

		if (code != LDAP_SUCCESS)
			g_warning ("operation to get LDAP server info failed: %s", message);

		ldap_memfree (message);

		g_simple_async_result_complete_in_idle (res);
		seahorse_progress_end (closure->cancellable, res);
		return FALSE; /* don't callback again */
	}
}
Пример #8
0
NS_IMETHODIMP
nsLDAPMessage::GetType(PRInt32 *aType)
{
    if (!aType) {
        return NS_ERROR_ILLEGAL_VALUE;
    }

    *aType = ldap_msgtype(mMsgHandle);
    if (*aType == -1) {
        return NS_ERROR_UNEXPECTED;
    };

    return NS_OK;
}
Пример #9
0
static void ldap_bind_lookup_dn_callback(struct ldap_connection *conn,
					 struct ldap_request *ldap_request,
					 LDAPMessage *res)
{
	struct passdb_ldap_request *passdb_ldap_request =
		(struct passdb_ldap_request *)ldap_request;
	struct auth_request *auth_request = ldap_request->auth_request;
	struct passdb_ldap_request *brequest;
	char *dn;

	if (res != NULL && ldap_msgtype(res) == LDAP_RES_SEARCH_ENTRY) {
		if (passdb_ldap_request->entries++ > 0) {
			/* too many replies */
			return;
		}

		/* first entry */
		ldap_query_save_result(conn, auth_request,
				       &passdb_ldap_request->request.search, res);

		/* save dn */
		dn = ldap_get_dn(conn->ld, res);
		passdb_ldap_request->dn = p_strdup(auth_request->pool, dn);
		ldap_memfree(dn);
	} else if (res == NULL || passdb_ldap_request->entries != 1) {
		/* failure */
		ldap_bind_lookup_dn_fail(auth_request, passdb_ldap_request, res);
	} else if (auth_request->skip_password_check) {
		/* we've already verified that the password matched -
		   we just wanted to get any extra fields */
		passdb_ldap_request->callback.
			verify_plain(PASSDB_RESULT_OK, auth_request);
		auth_request_unref(&auth_request);
	} else {
		/* create a new bind request */
		brequest = p_new(auth_request->pool,
				 struct passdb_ldap_request, 1);
		brequest->dn = passdb_ldap_request->dn;
		brequest->callback = passdb_ldap_request->callback;
		brequest->request.bind.dn = brequest->dn;
		brequest->request.bind.request.type = LDAP_REQUEST_TYPE_BIND;
		brequest->request.bind.request.auth_request = auth_request;

		ldap_auth_bind(conn, &brequest->request.bind);
	}
}
Пример #10
0
static void
ldap_lookup_pass_callback(struct ldap_connection *conn,
			  struct ldap_request *request, LDAPMessage *res)
{
	struct passdb_ldap_request *ldap_request =
		(struct passdb_ldap_request *)request;
        struct auth_request *auth_request = request->auth_request;

	if (res == NULL || ldap_msgtype(res) == LDAP_RES_SEARCH_RESULT) {
		ldap_lookup_finish(auth_request, ldap_request, res);
		auth_request_unref(&auth_request);
		return;
	}

	if (ldap_request->entries++ == 0) {
		/* first entry */
		ldap_query_save_result(conn, res, auth_request);
	}
}
Пример #11
0
static void userdb_ldap_lookup_callback(struct ldap_connection *conn,
					struct ldap_request *request,
					LDAPMessage *res)
{
	struct userdb_ldap_request *urequest =
		(struct userdb_ldap_request *) request;
	struct auth_request *auth_request =
		urequest->request.request.auth_request;

	if (res == NULL || ldap_msgtype(res) == LDAP_RES_SEARCH_RESULT) {
		userdb_ldap_lookup_finish(auth_request, urequest, res);
		auth_request_unref(&auth_request);
		return;
	}

	if (urequest->entries++ == 0) {
		/* first entry */
		ldap_query_get_result(conn, auth_request,
				      &urequest->request, res);
	}
}
Пример #12
0
static void userdb_ldap_iterate_callback(struct ldap_connection *conn,
					 struct ldap_request *request,
					 LDAPMessage *res)
{
	struct userdb_iter_ldap_request *urequest =
		(struct userdb_iter_ldap_request *)request;
	struct ldap_userdb_iterate_context *ctx = urequest->ctx;
	struct db_ldap_result_iterate_context *ldap_iter;
	const char *name, *const *values;

	if (res == NULL || ldap_msgtype(res) == LDAP_RES_SEARCH_RESULT) {
		if (res == NULL)
			ctx->ctx.failed = TRUE;
		ctx->ctx.callback(NULL, ctx->ctx.context);
		return;
	}

	/* the iteration can take a while. reset the request's create time so
	   it won't be aborted while it's still running */
	request->create_time = ioloop_time;

	ctx->in_callback = TRUE;
	ldap_iter = db_ldap_result_iterate_init(conn, &urequest->request,
						res, TRUE);
	while (db_ldap_result_iterate_next(ldap_iter, &name, &values)) {
		if (strcmp(name, "user") != 0) {
			i_warning("ldap: iterate: "
				  "Ignoring field not named 'user': %s", name);
			continue;
		}
		for (; *values != NULL; values++) {
			ctx->continued = FALSE;
			ctx->ctx.callback(*values, ctx->ctx.context);
		}
	}
	db_ldap_result_iterate_deinit(&ldap_iter);
	if (!ctx->continued)
		db_ldap_enable_input(conn, FALSE);
	ctx->in_callback = FALSE;
}
Пример #13
0
static void ldap_bind_lookup_dn_callback(struct ldap_connection *conn,
					 struct ldap_request *ldap_request,
					 LDAPMessage *res)
{
	struct passdb_ldap_request *passdb_ldap_request =
		(struct passdb_ldap_request *)ldap_request;
	struct auth_request *auth_request = ldap_request->auth_request;
	struct passdb_ldap_request *brequest;
	char *dn;

	if (res != NULL && ldap_msgtype(res) == LDAP_RES_SEARCH_ENTRY) {
		if (passdb_ldap_request->entries++ > 0) {
			/* too many replies */
			return;
		}

		/* first entry */
		ldap_query_save_result(conn, auth_request,
				       &passdb_ldap_request->request.search, res);

		/* save dn */
		dn = ldap_get_dn(conn->ld, res);
		passdb_ldap_request->dn = p_strdup(auth_request->pool, dn);
		ldap_memfree(dn);
	} else if (res == NULL || passdb_ldap_request->entries != 1) {
		/* failure */
		ldap_bind_lookup_dn_fail(auth_request, passdb_ldap_request, res);
	} else {
		/* create a new bind request */
		brequest = p_new(auth_request->pool,
				 struct passdb_ldap_request, 1);
		brequest->dn = passdb_ldap_request->dn;
		brequest->callback = passdb_ldap_request->callback;
		brequest->request.bind.dn = brequest->dn;
		brequest->request.bind.request.type = LDAP_REQUEST_TYPE_BIND;
		brequest->request.bind.request.auth_request = auth_request;

		ldap_auth_bind(conn, &brequest->request.bind);
	}
}
Пример #14
0
/*
 * poll for new responses
 */
int
ldap_sync_poll( ldap_sync_t *ls )
{
	struct	timeval		tv,
				*tvp = NULL;
	LDAPMessage		*res = NULL,
				*msg;
	int			rc = 0;

#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "ldap_sync_poll...\n" );
#endif /* LDAP_SYNC_TRACE */

	assert( ls != NULL );
	assert( ls->ls_ld != NULL );

	if ( ls->ls_timeout != -1 ) {
		tv.tv_sec = ls->ls_timeout;
		tv.tv_usec = 0;
		tvp = &tv;
	}

	rc = ldap_result( ls->ls_ld, ls->ls_msgid,
		LDAP_MSG_RECEIVED, tvp, &res );
	if ( rc <= 0 ) {
		return rc;
	}

	for ( msg = ldap_first_message( ls->ls_ld, res );
		msg;
		msg = ldap_next_message( ls->ls_ld, msg ) )
	{
		int	refreshDone;

		switch ( ldap_msgtype( msg ) ) {
		case LDAP_RES_SEARCH_ENTRY:
			rc = ldap_sync_search_entry( ls, res );
			break;

		case LDAP_RES_SEARCH_REFERENCE:
			rc = ldap_sync_search_reference( ls, res );
			break;

		case LDAP_RES_SEARCH_RESULT:
			rc = ldap_sync_search_result( ls, res );
			goto done_search;

		case LDAP_RES_INTERMEDIATE:
			rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
			if ( rc != LDAP_SUCCESS || refreshDone ) {
				goto done_search;
			}
			break;

		default:
#ifdef LDAP_SYNC_TRACE
			fprintf( stderr, "\tgot something unexpected...\n" );
#endif /* LDAP_SYNC_TRACE */

			ldap_msgfree( res );

			rc = LDAP_OTHER;
			goto done;
		}
	}

done_search:;
	ldap_msgfree( res );

done:;
	return rc;
}
Пример #15
0
/*
 * initialize the sync
 */
int
ldap_sync_init( ldap_sync_t *ls, int mode )
{
	LDAPControl	ctrl = { 0 },
			*ctrls[ 2 ];
	BerElement	*ber = NULL;
	int		rc;
	struct timeval	tv = { 0 },
			*tvp = NULL;
	LDAPMessage	*res = NULL;

#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "ldap_sync_init(%s)...\n",
		mode == LDAP_SYNC_REFRESH_AND_PERSIST ?
			"LDAP_SYNC_REFRESH_AND_PERSIST" :
			( mode == LDAP_SYNC_REFRESH_ONLY ?
				"LDAP_SYNC_REFRESH_ONLY" : "unknown" ) );
#endif /* LDAP_SYNC_TRACE */

	assert( ls != NULL );
	assert( ls->ls_ld != NULL );

	/* support both refreshOnly and refreshAndPersist */
	switch ( mode ) {
	case LDAP_SYNC_REFRESH_AND_PERSIST:
	case LDAP_SYNC_REFRESH_ONLY:
		break;

	default:
		fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode );
		return LDAP_PARAM_ERROR;
	}

	/* check consistency of cookie and reloadHint at initial refresh */
	if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) {
		fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" );
		return LDAP_PARAM_ERROR;
	}

	ctrls[ 0 ] = &ctrl;
	ctrls[ 1 ] = NULL;

	/* prepare the Sync Request control */
	ber = ber_alloc_t( LBER_USE_DER );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "%sber_alloc_t() %s= NULL\n",
		ber == NULL ? "!!! " : "",
		ber == NULL ? "=" : "!" );
#endif /* LDAP_SYNC_TRACE */
	if ( ber == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto done;
	}

	ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE;

	if ( ls->ls_cookie.bv_val != NULL ) {
		ber_printf( ber, "{eOb}", mode,
			&ls->ls_cookie, ls->ls_reloadHint );

	} else {
		ber_printf( ber, "{eb}", mode, ls->ls_reloadHint );
	}

	rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr,
		"%sber_flatten2() == %d\n",
		rc ? "!!! " : "",
		rc );
#endif /* LDAP_SYNC_TRACE */
	if ( rc < 0 ) {
		rc = LDAP_OTHER;
                goto done;
        }

	/* make the control critical, as we cannot proceed without */
	ctrl.ldctl_oid = LDAP_CONTROL_SYNC;
	ctrl.ldctl_iscritical = 1;

	/* timelimit? */
	if ( ls->ls_timelimit ) {
		tv.tv_sec = ls->ls_timelimit;
		tvp = &tv;
	}

	/* actually run the search */
	rc = ldap_search_ext( ls->ls_ld,
		ls->ls_base, ls->ls_scope, ls->ls_filter,
		ls->ls_attrs, 0, ctrls, NULL,
		tvp, ls->ls_sizelimit, &ls->ls_msgid );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr,
		"%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n",
		rc ? "!!! " : "",
		ls->ls_base, ls->ls_scope, ls->ls_filter, rc );
#endif /* LDAP_SYNC_TRACE */
	if ( rc != LDAP_SUCCESS ) {
		goto done;
	}

	/* initial content/content update phase */
	for ( ; ; ) {
		LDAPMessage	*msg = NULL;

		/* NOTE: this very short timeout is just to let
		 * ldap_result() yield long enough to get something */
		tv.tv_sec = 0;
		tv.tv_usec = 100000;

		rc = ldap_result( ls->ls_ld, ls->ls_msgid,
			LDAP_MSG_RECEIVED, &tv, &res );
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr,
			"\t%sldap_result(%d) == %d\n",
			rc == -1 ? "!!! " : "",
			ls->ls_msgid, rc );
#endif /* LDAP_SYNC_TRACE */
		switch ( rc ) {
		case 0:
			/*
			 * timeout
			 *
			 * TODO: can do something else in the meanwhile)
			 */
			break;

		case -1:
			/* smtg bad! */
			goto done;

		default:
			for ( msg = ldap_first_message( ls->ls_ld, res );
				msg != NULL;
				msg = ldap_next_message( ls->ls_ld, msg ) )
			{
				int	refreshDone;

				switch ( ldap_msgtype( msg ) ) {
				case LDAP_RES_SEARCH_ENTRY:
					rc = ldap_sync_search_entry( ls, res );
					break;

				case LDAP_RES_SEARCH_REFERENCE:
					rc = ldap_sync_search_reference( ls, res );
					break;

				case LDAP_RES_SEARCH_RESULT:
					rc = ldap_sync_search_result( ls, res );
					goto done_search;

				case LDAP_RES_INTERMEDIATE:
					rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
					if ( rc != LDAP_SUCCESS || refreshDone ) {
						goto done_search;
					}
					break;

				default:
#ifdef LDAP_SYNC_TRACE
					fprintf( stderr, "\tgot something unexpected...\n" );
#endif /* LDAP_SYNC_TRACE */

					ldap_msgfree( res );

					rc = LDAP_OTHER;
					goto done;
				}
			}
			ldap_msgfree( res );
			res = NULL;
			break;
		}
	}

done_search:;
	ldap_msgfree( res );

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return rc;
}
Пример #16
0
/*
 * ldap_load:
 * opens the connection only if needed.
 */
static LibBalsaABErr
libbalsa_address_book_ldap_load(LibBalsaAddressBook * ab,
                                const gchar *filter,
                                LibBalsaAddressBookLoadFunc callback,
                                gpointer closure)
{
    LibBalsaAddressBookLdap *ldap_ab;
    LibBalsaAddress *address;
    LDAPMessage *msg, *result;
    int msgid, rc, attempt;
    gchar *ldap_filter;

    g_return_val_if_fail ( LIBBALSA_IS_ADDRESS_BOOK_LDAP(ab), LBABERR_OK);

    if (callback == NULL)
	return LBABERR_OK;

    ldap_ab = LIBBALSA_ADDRESS_BOOK_LDAP(ab);
    /*
     * Connect to the server.
     */
    for(attempt=0; attempt<2; attempt++) {
        if (ldap_ab->directory == NULL) {
            if ((rc=libbalsa_address_book_ldap_open_connection(ldap_ab))
                != LDAP_SUCCESS)
                return LBABERR_CANNOT_CONNECT;
        }
        
        /* 
         * Attempt to search for e-mail addresses. It returns success 
         * or failure, but not all the matches. 
         * we use the asynchronous lookup to fetch the results in chunks
         * in case we exceed administrative limits.
         */ 
        /* g_print("Performing full lookup…\n"); */
        ldap_filter = filter 
            ? g_strdup_printf("(&(objectClass=organizationalPerson)(mail=*)"
                              "(|(cn=%s*)(sn=%s*)(mail=%s*@*)))",
                              filter, filter, filter)
            : g_strdup("(&(objectClass=organizationalPerson)(mail=*))");
	if(DEBUG_LDAP)
	    g_print("Send LDAP request: %s (basedn=%s)\n", ldap_filter,
		    ldap_ab->base_dn);
        if(ldap_search_ext(ldap_ab->directory, ldap_ab->base_dn,
                           LDAP_SCOPE_SUBTREE, 
                           ldap_filter, book_attrs, 0, NULL, NULL,
                           NULL, ABL_SIZE_LIMIT, &msgid) != LDAP_SUCCESS) {
            libbalsa_address_book_ldap_close_connection(ldap_ab);
            continue; /* try again */
        }
        /* 
         * Now loop over all the results, and spit out the output.
         */
        
        while((rc=ldap_result(ldap_ab->directory, msgid, 
                              LDAP_MSG_ONE, NULL, &result))>0) {
            msg = ldap_first_entry(ldap_ab->directory, result);
            if (!msg || ldap_msgtype( msg ) == LDAP_RES_SEARCH_RESULT)
                break;
            address = libbalsa_address_book_ldap_get_address(ab, msg);
            callback(ab, address, closure);
            g_object_unref(address);
        }
        if(rc == -1) { /* try again */
            libbalsa_address_book_ldap_close_connection(ldap_ab);
            continue;
	}
        callback(ab, NULL, closure);
        ldap_msgfree(result);
        libbalsa_address_book_set_status(ab, NULL);
        return LBABERR_OK;
    }
    /* we have tried and failed... */
    /* extended status? */
    return LBABERR_CANNOT_SEARCH;
}
Пример #17
0
/** 
 * Initializes a message.
 *
 * @param aConnection           The nsLDAPConnection this message is on
 * @param aMsgHandle            The native LDAPMessage to be wrapped.
 * 
 * @exception NS_ERROR_ILLEGAL_VALUE        null pointer passed in
 * @exception NS_ERROR_UNEXPECTED           internal err; shouldn't happen
 * @exception NS_ERROR_LDAP_DECODING_ERROR  problem during BER decoding
 * @exception NS_ERROR_OUT_OF_MEMORY        ran out of memory
 */
nsresult 
nsLDAPMessage::Init(nsILDAPConnection *aConnection, LDAPMessage *aMsgHandle)
{
    int parseResult; 

    if (!aConnection || !aMsgHandle) {
        NS_WARNING("Null pointer passed in to nsLDAPMessage::Init()");
        return NS_ERROR_ILLEGAL_VALUE;
    }

    // initialize the appropriate member vars
    //
    mConnection = aConnection;
    mMsgHandle = aMsgHandle;

    // cache the connection handle.  we're violating the XPCOM type-system
    // here since we're a friend of the connection class and in the 
    // same module.
    //
    mConnectionHandle = static_cast<nsLDAPConnection *>(aConnection)->mConnectionHandle;

    // do any useful message parsing
    //
    const int msgType = ldap_msgtype(mMsgHandle);
    if ( msgType == -1) {
        NS_ERROR("nsLDAPMessage::Init(): ldap_msgtype() failed");
        return NS_ERROR_UNEXPECTED;
    }

    switch (msgType) {

    case LDAP_RES_SEARCH_REFERENCE:
        // XXX should do something here?
        break;

    case LDAP_RES_SEARCH_ENTRY:
        // nothing to do here
        break;

    case LDAP_RES_EXTENDED:
        // XXX should do something here?
        break;

    case LDAP_RES_BIND:
    case LDAP_RES_SEARCH_RESULT:
    case LDAP_RES_MODIFY:
    case LDAP_RES_ADD:
    case LDAP_RES_DELETE:
    case LDAP_RES_MODRDN:
    case LDAP_RES_COMPARE:
        parseResult = ldap_parse_result(mConnectionHandle, 
                                        mMsgHandle, &mErrorCode, &mMatchedDn,
                                        &mErrorMessage,&mReferrals, 
                                        &mServerControls, 0);
        switch (parseResult) {
        case LDAP_SUCCESS: 
            // we're good
            break;

        case LDAP_DECODING_ERROR:
            NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() hit a "
                       "decoding error");
            return NS_ERROR_LDAP_DECODING_ERROR;

        case LDAP_NO_MEMORY:
            NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() ran out " 
                       "of memory");
            return NS_ERROR_OUT_OF_MEMORY;

        case LDAP_PARAM_ERROR:
        case LDAP_MORE_RESULTS_TO_RETURN:
        case LDAP_NO_RESULTS_RETURNED:
        default:
            NS_ERROR("nsLDAPMessage::Init(): ldap_parse_result returned "
                     "unexpected return code");
            return NS_ERROR_UNEXPECTED;
        }

        break;

    default:
        NS_ERROR("nsLDAPMessage::Init(): unexpected message type");
        return NS_ERROR_UNEXPECTED;
    }

    return NS_OK;
}
Пример #18
0
int
asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate)
{
	a_metainfo_t	*mi;
	a_metatarget_t	*mt;
	a_metasingleconn_t *msc;
	Operation *op = bc->op;
	SlapReply *rs;
	int	   i, rc = LDAP_SUCCESS, sres;
	SlapReply *candidates;
	char		**references = NULL;
	LDAPControl	**ctrls = NULL;
	a_dncookie dc;
	LDAPMessage *msg;
	ber_int_t id;

	rs = &bc->rs;
	mi = mc->mc_info;
	mt = mi->mi_targets[ candidate ];
	msc = &mc->mc_conns[ candidate ];
	dc.op = op;
	dc.target = mt;
	dc.to_from = MASSAGE_REP;
	id = ldap_msgid(res);


	candidates = bc->candidates;
	i = candidate;

	while (res && !META_BACK_CONN_INVALID(msc)) {
	for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) {
		switch(ldap_msgtype(msg)) {
		case LDAP_RES_SEARCH_ENTRY:
			Debug( LDAP_DEBUG_TRACE,
				"%s asyncmeta_handle_search_msg: msc %p entry\n",
				op->o_log_prefix, msc );
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			/* count entries returned by target */
			candidates[ i ].sr_nentries++;
			if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) {
				rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg );
			} else {
				goto err_cleanup;
			}
			switch ( rs->sr_err ) {
			case LDAP_SIZELIMIT_EXCEEDED:
				asyncmeta_send_ldap_result(bc, op, rs);
				rs->sr_err = LDAP_SUCCESS;
				goto err_cleanup;
			case LDAP_UNAVAILABLE:
				rs->sr_err = LDAP_OTHER;
				break;
			default:
				break;
			}
			bc->is_ok++;
			break;

		case LDAP_RES_SEARCH_REFERENCE:
			if ( META_BACK_TGT_NOREFS( mt ) ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;
			rc = ldap_parse_reference( msc->msc_ldr, msg,
				   &references, &rs->sr_ctrls, 0 );

			if ( rc != LDAP_SUCCESS || references == NULL ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			/* FIXME: merge all and return at the end */

			{
				int cnt;
				for ( cnt = 0; references[ cnt ]; cnt++ )
					;

				rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

				for ( cnt = 0; references[ cnt ]; cnt++ ) {
					ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ],
							  op->o_tmpmemctx );
				}
				BER_BVZERO( &rs->sr_ref[ cnt ] );
			}

			{
				dc.memctx = op->o_tmpmemctx;
				( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref );
			}

			if ( rs->sr_ref != NULL ) {
				if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
					/* ignore return value by now */
					( void )send_search_reference( op, rs );
				}

				ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
				rs->sr_ref = NULL;
			}

			/* cleanup */
			if ( references ) {
				ber_memvfree( (void **)references );
			}

			if ( rs->sr_ctrls ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_INTERMEDIATE:
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;

			/* FIXME: response controls
			 * are passed without checks */
			rs->sr_err = ldap_parse_intermediate( msc->msc_ldr,
								  msg,
								  (char **)&rs->sr_rspoid,
								  &rs->sr_rspdata,
								  &rs->sr_ctrls,
								  0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_type = REP_RESULT;
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			slap_send_ldap_intermediate( op, rs );

			if ( rs->sr_rspoid != NULL ) {
				ber_memfree( (char *)rs->sr_rspoid );
				rs->sr_rspoid = NULL;
			}

			if ( rs->sr_rspdata != NULL ) {
				ber_bvfree( rs->sr_rspdata );
				rs->sr_rspdata = NULL;
			}

			if ( rs->sr_ctrls != NULL ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_SEARCH_RESULT:
			if ( mi->mi_idle_timeout != 0 ) {
				asyncmeta_set_msc_time(msc);
			}
			Debug( LDAP_DEBUG_TRACE,
			       "%s asyncmeta_handle_search_msg: msc %p result\n",
			       op->o_log_prefix, msc );
			candidates[ i ].sr_type = REP_RESULT;
			candidates[ i ].sr_msgid = META_MSGID_IGNORE;
			/* NOTE: ignores response controls
			 * (and intermediate response controls
			 * as well, except for those with search
			 * references); this may not be correct,
			 * but if they're not ignored then
			 * back-meta would need to merge them
			 * consistently (think of pagedResults...)
			 */
			/* FIXME: response controls? */
			rs->sr_err = ldap_parse_result( msc->msc_ldr,
							msg,
							&candidates[ i ].sr_err,
								(char **)&candidates[ i ].sr_matched,
							(char **)&candidates[ i ].sr_text,
							&references,
							&ctrls /* &candidates[ i ].sr_ctrls (unused) */ ,
							0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_err = rs->sr_err;
				sres = slap_map_api2result( &candidates[ i ] );
				candidates[ i ].sr_type = REP_RESULT;
				goto finish;
			}

			rs->sr_err = candidates[ i ].sr_err;

			/* massage matchedDN if need be */
			if ( candidates[ i ].sr_matched != NULL ) {
				struct berval	match, mmatch;

				ber_str2bv( candidates[ i ].sr_matched,
						0, 0, &match );
				candidates[ i ].sr_matched = NULL;

				dc.memctx = NULL;
				asyncmeta_dn_massage( &dc, &match, &mmatch );
				if ( mmatch.bv_val == match.bv_val ) {
					candidates[ i ].sr_matched
						= ch_strdup( mmatch.bv_val );

				} else {
					candidates[ i ].sr_matched = mmatch.bv_val;
				}

				bc->candidate_match++;
				ldap_memfree( match.bv_val );
			}

			/* add references to array */
			/* RFC 4511: referrals can only appear
			 * if result code is LDAP_REFERRAL */
			if ( references != NULL
				 && references[ 0 ] != NULL
				 && references[ 0 ][ 0 ] != '\0' )
			{
				if ( rs->sr_err != LDAP_REFERRAL ) {
					Debug( LDAP_DEBUG_ANY,
						   "%s asncmeta_search_result[%d]: "
						   "got referrals with err=%d\n",
						   op->o_log_prefix,
						   i, rs->sr_err );

				} else {
					BerVarray	sr_ref;
					int		cnt;

					for ( cnt = 0; references[ cnt ]; cnt++ )
						;

					sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

					for ( cnt = 0; references[ cnt ]; cnt++ ) {
						ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ],
								  op->o_tmpmemctx );
					}
					BER_BVZERO( &sr_ref[ cnt ] );

					dc.memctx = op->o_tmpmemctx;
					( void )asyncmeta_referral_result_rewrite( &dc, sr_ref );

					if ( rs->sr_v2ref == NULL ) {
						rs->sr_v2ref = sr_ref;

					} else {
						for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
							ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ],
									   op->o_tmpmemctx );
						}
						ber_memfree_x( sr_ref, op->o_tmpmemctx );
					}
				}

			} else if ( rs->sr_err == LDAP_REFERRAL ) {
				Debug( LDAP_DEBUG_TRACE,
					   "%s asyncmeta_search_result[%d]: "
					   "got err=%d with null "
					   "or empty referrals\n",
					   op->o_log_prefix,
					   i, rs->sr_err );

				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}

			/* cleanup */
			ber_memvfree( (void **)references );

			sres = slap_map_api2result( rs );

			if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
				       (long) candidates[ i ].sr_err );
			} else {
					Debug( LDAP_DEBUG_ANY,  "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld (%s)",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
					       (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) );
			}

			switch ( sres ) {
			case LDAP_NO_SUCH_OBJECT:
				/* is_ok is touched any time a valid
				 * (even intermediate) result is
				 * returned; as a consequence, if
				 * a candidate returns noSuchObject
				 * it is ignored and the candidate
				 * is simply demoted. */
				if ( bc->is_ok ) {
					sres = LDAP_SUCCESS;
				}
				break;

			case LDAP_SUCCESS:
				if ( ctrls != NULL && ctrls[0] != NULL ) {
#ifdef SLAPD_META_CLIENT_PR
					LDAPControl *pr_c;

					pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
					if ( pr_c != NULL ) {
						BerElementBuffer berbuf;
						BerElement *ber = (BerElement *)&berbuf;
						ber_tag_t tag;
						ber_int_t prsize;
						struct berval prcookie;

						/* unsolicited, do not accept */
						if ( mt->mt_ps == 0 ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER );

						tag = ber_scanf( ber, "{im}", &prsize, &prcookie );
						if ( tag == LBER_ERROR ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						/* more pages? new search request */
						if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) {
							if ( mt->mt_ps > 0 ) {
								/* ignore size if specified */
								prsize = 0;

							} else if ( prsize == 0 ) {
								/* guess the page size from the entries returned so far */
								prsize = candidates[ i ].sr_nentries;
							}

							candidates[ i ].sr_nentries = 0;
							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
							candidates[ i ].sr_type = REP_INTERMEDIATE;

							assert( candidates[ i ].sr_matched == NULL );
							assert( candidates[ i ].sr_text == NULL );
							assert( candidates[ i ].sr_ref == NULL );

							switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) )
							{
							case META_SEARCH_CANDIDATE:
								assert( candidates[ i ].sr_msgid >= 0 );
								ldap_controls_free( ctrls );
								//	goto free_message;

							case META_SEARCH_ERR:
							case META_SEARCH_NEED_BIND:
err_pr:;
								candidates[ i ].sr_err = rs->sr_err;
								candidates[ i ].sr_type = REP_RESULT;
								if ( META_BACK_ONERR_STOP( mi ) ) {
									asyncmeta_send_ldap_result(bc, op, rs);
									ldap_controls_free( ctrls );
									goto err_cleanup;
								}
								/* fallthru */

							case META_SEARCH_NOT_CANDIDATE:
								/* means that asyncmeta_back_search_start()
								 * failed but onerr == continue */
								candidates[ i ].sr_msgid = META_MSGID_IGNORE;
								candidates[ i ].sr_type = REP_RESULT;
								break;

							default:
								/* impossible */
								assert( 0 );
								break;
							}
							break;
						}
					}
#endif /* SLAPD_META_CLIENT_PR */

					ldap_controls_free( ctrls );
				}
				/* fallthru */

			case LDAP_REFERRAL:
				bc->is_ok++;
				break;

			case LDAP_SIZELIMIT_EXCEEDED:
				/* if a target returned sizelimitExceeded
				 * and the entry count is equal to the
				 * proxy's limit, the target would have
				 * returned more, and the error must be
				 * propagated to the client; otherwise,
				 * the target enforced a limit lower
				 * than what requested by the proxy;
				 * ignore it */
				candidates[ i ].sr_err = rs->sr_err;
				if ( rs->sr_nentries == op->ors_slimit
					 || META_BACK_ONERR_STOP( mi ) )
				{
					const char *save_text;
got_err:
					save_text = rs->sr_text;
					rs->sr_text = candidates[ i ].sr_text;
					asyncmeta_send_ldap_result(bc, op, rs);
					if (candidates[ i ].sr_text != NULL) {
						ch_free( (char *)candidates[ i ].sr_text );
						candidates[ i ].sr_text = NULL;
					}
					rs->sr_text = save_text;
					ldap_controls_free( ctrls );
					goto err_cleanup;
				}
				break;

			default:
				candidates[ i ].sr_err = rs->sr_err;
				if ( META_BACK_ONERR_STOP( mi ) ) {
					goto got_err;
				}
				break;
			}
			/* if this is the last result we will ever receive, send it back  */
			rc = rs->sr_err;
			if (asyncmeta_is_last_result(mc, bc, i) == 0) {
				Debug( LDAP_DEBUG_TRACE,
					"%s asyncmeta_handle_search_msg: msc %p last result\n",
					op->o_log_prefix, msc );
				asyncmeta_search_last_result(mc, bc, i, sres);
err_cleanup:
				rc = rs->sr_err;
				ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
				asyncmeta_drop_bc( mc, bc);
				asyncmeta_clear_bm_context(bc);
				ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
				ldap_msgfree(res);
				return rc;
			}
finish:
			break;

		default:
			continue;
		}
	}
		ldap_msgfree(res);
		res = NULL;
		if (candidates[ i ].sr_type != REP_RESULT) {
			struct timeval	tv = {0};
			rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res );
			if (res != NULL) {
				msc->msc_result_time = slap_get_time();
			}
		}
	}
	ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
	bc->bc_active--;
	ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );

	return rc;
}
Пример #19
0
void *
asyncmeta_op_handle_result(void *ctx, void *arg)
{
	a_metaconn_t *mc = arg;
	int		i, j, rc, ntargets;
	struct timeval	tv = {0};
	LDAPMessage     *msg;
	a_metasingleconn_t *msc;
	bm_context_t *bc;
	void *oldctx;

	ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
	rc = ++mc->mc_active;
	ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
	if (rc > 1)
		return NULL;

	ntargets = mc->mc_info->mi_ntargets;
	i = ntargets;
	oldctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx, 0);	/* get existing memctx */

again:
	for (j=0; j<ntargets; j++) {
		i++;
		if (i >= ntargets) i = 0;
		msc = &mc->mc_conns[i];
		ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
		if (!mc->mc_conns[i].msc_ldr ||
		    META_BACK_CONN_CREATING( &mc->mc_conns[i] ) ||
		    META_BACK_CONN_INVALID(&mc->mc_conns[i])) {
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
			continue;
		}

		msc->msc_active++;
		ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );

		rc = ldap_result( mc->mc_conns[i].msc_ldr, LDAP_RES_ANY, LDAP_MSG_RECEIVED, &tv, &msg );
		if (rc < 1) {
			if (rc < 0) {
				ldap_get_option( mc->mc_conns[i].msc_ldr, LDAP_OPT_ERROR_NUMBER, &rc);
				META_BACK_CONN_INVALID_SET(&mc->mc_conns[i]);
				asyncmeta_op_read_error(mc, i, rc, ctx);
			}
			ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
			msc->msc_active--;
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
			continue;
		}
		rc = ldap_msgtype( msg );
		if (rc == LDAP_RES_BIND) {
			if ( LogTest( asyncmeta_debug ) ) {
				char	time_buf[ SLAP_TEXT_BUFLEN ];
				asyncmeta_get_timestamp(time_buf);
				Debug( asyncmeta_debug, "[%s] asyncmeta_op_handle_result received bind msgid=%d msc: %p\n",
				      time_buf, ldap_msgid(msg), msc );
			}
			asyncmeta_handle_bind_result(msg, mc, i, ctx);
			mc->mc_info->mi_targets[i]->mt_timeout_ops = 0;
			ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
			msc->msc_result_time = slap_get_time();
			msc->msc_active--;
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
			if (msg)
				ldap_msgfree(msg);

			continue;
		}
retry_bc:
		ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
		bc = asyncmeta_find_message(ldap_msgid(msg), mc, i);
/* The sender might not be yet done with the context. On error it might also remove it
 * so it's best to try and find it again after a wait */
		if (bc && bc->bc_active > 0) {
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
			ldap_pvt_thread_yield();
			goto retry_bc;
		}
		if (bc) {
			bc->bc_active++;
		}

		msc->msc_result_time = slap_get_time();
		msc->msc_active--;
		ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
		if (!bc) {
			Debug( asyncmeta_debug,
				"asyncmeta_op_handle_result: Unable to find bc for msguid %d, msc: %p\n", ldap_msgid(msg), msc );
			ldap_msgfree(msg);
			continue;
		}

		/* set our memctx */
		bc->op->o_threadctx = ctx;
		bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
		slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
		if (bc->op->o_abandon) {
			ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
			asyncmeta_drop_bc( mc, bc);
			if ( bc->op->o_tag == LDAP_REQ_SEARCH ) {
				int j;
				for (j=0; j<ntargets; j++) {
					if (bc->candidates[j].sr_msgid >= 0) {
						a_metasingleconn_t *tmp_msc = &mc->mc_conns[j];
						tmp_msc->msc_active++;
						asyncmeta_back_cancel( mc, bc->op,
								       bc->candidates[ j ].sr_msgid, j );
						tmp_msc->msc_active--;
					}
				}
			}
			asyncmeta_clear_bm_context(bc);
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
			if (msg)
				ldap_msgfree(msg);
			continue;
		}

		switch (rc) {
		case LDAP_RES_SEARCH_ENTRY:
		case LDAP_RES_SEARCH_REFERENCE:
		case LDAP_RES_SEARCH_RESULT:
		case LDAP_RES_INTERMEDIATE:
			asyncmeta_handle_search_msg(msg, mc, bc, i);
			mc->mc_info->mi_targets[i]->mt_timeout_ops = 0;
			msg = NULL;
			break;
		case LDAP_RES_ADD:
		case LDAP_RES_DELETE:
		case LDAP_RES_MODDN:
		case LDAP_RES_COMPARE:
		case LDAP_RES_MODIFY:
			rc = asyncmeta_handle_common_result(msg, mc, bc, i);
			mc->mc_info->mi_targets[i]->mt_timeout_ops = 0;
			break;
		default:
			{
			Debug( asyncmeta_debug,
				   "asyncmeta_op_handle_result: "
				   "unrecognized response message tag=%d\n",
				   rc );

			}
		}
		if (msg)
			ldap_msgfree(msg);
	}

	ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
	rc = --mc->mc_active;
	ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
	if (rc) {
		i++;
		goto again;
	}
	slap_sl_mem_setctx(ctx, oldctx);
	if (mc->mc_conns) {
		ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
		for (i=0; i<ntargets; i++) {
			if (!slapd_shutdown && !META_BACK_CONN_INVALID(msc)
			    && mc->mc_conns[i].msc_ldr && mc->mc_conns[i].conn) {
				connection_client_enable(mc->mc_conns[i].conn);
			}
		}
		ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
	}
	return NULL;
}
Пример #20
0
int ld_cmd_exec(db_res_t* res, db_cmd_t* cmd)
{
	db_con_t* con;
	struct ld_res* lres;
	struct ld_cmd* lcmd;
	struct ld_con* lcon;
	char* filter, *err_desc;
	int ret, err;
	LDAPMessage *msg, *resmsg;
	int reconn_cnt;
	int msgid;
	char *oid;
	struct berval *data;
	struct timeval restimeout;

	filter = NULL;
	err_desc = NULL;
	resmsg = NULL;

	/* First things first: retrieve connection info from the currently active
	 * connection and also mysql payload from the database command
	 */
	con = cmd->ctx->con[db_payload_idx];
	lcmd = DB_GET_PAYLOAD(cmd);
	lcon = DB_GET_PAYLOAD(con);
	
	reconn_cnt = ld_reconnect_attempt;

	if (ld_prepare_ldap_filter(&filter, cmd, &lcmd->filter) < 0) {
		ERR("ldap: Error while building LDAP search filter\n");
		goto error;
	}

	DBG("ldap: ldap_search(base:'%s', filter:'%s')\n", lcmd->base, filter);
	do {
		if (lcon->flags & LD_CONNECTED) {
			ldap_set_option(lcon->con, LDAP_OPT_DEREF, ((void *)&lcmd->chase_references));
			/* there is alternative method using LDAP_CONTROL_REFERRALS per request but is not well documented */
			ldap_set_option(lcon->con, LDAP_OPT_REFERRALS, lcmd->chase_referrals?LDAP_OPT_ON:LDAP_OPT_OFF);
		
			ret = ldap_search_ext(lcon->con, lcmd->base, lcmd->scope, filter,
								  lcmd->result, 0, NULL, NULL,
								  lcmd->timelimit.tv_sec ? &lcmd->timelimit : NULL,
								  lcmd->sizelimit,
								  &msgid);
			if (ret != LDAP_SUCCESS) {
				ERR("ldap: Error while searching: %s\n", ldap_err2string(ret));
				goto error;
			}

			/*
			 openldap v2.3 library workaround for unsolicited messages:
			 if only unsolicited messages are available then ldap_result of
			 v2.3 library waits forever
			*/
			memset(&restimeout, 0, sizeof(restimeout));
			restimeout.tv_sec = 5;
			ret = ldap_result(lcon->con,
							  LDAP_RES_ANY,
							  LDAP_MSG_ALL,
							  &restimeout,
							  &resmsg);
		} else {
			/* force it to reconnect */
			ret = -1;
		}

		if (ret <= 0) {
			ERR("ldap: Error in ldap_search: %s\n", ret < 0 ? ldap_err2string(ret) : "timeout");
			if (ret == LDAP_SERVER_DOWN) {
				lcon->flags &= ~LD_CONNECTED;
				do {
					if (!reconn_cnt) {
						ERR("ldap: maximum reconnection attempt reached! giving up\n");
						goto error;
					}
					reconn_cnt--;
					err = ld_con_connect(con);
				} while (err != 0);
			} else {
				goto error;
			}
		}
	} while (ret <= 0);

	/* looking for unsolicited messages */
	for (msg = ldap_first_message(lcon->con, resmsg);
		 msg != NULL;
		 msg = ldap_next_message(lcon->con, msg)) {
		if (ldap_msgtype(msg) == LDAP_RES_EXTENDED) {
			if (ldap_parse_extended_result(lcon->con,
										   msg,
										   &oid,
										   &data,
										   0) != LDAP_SUCCESS) {
				ERR("ldap: Error while parsing extended result\n");
 				goto error;
			}
			if (oid != NULL) {
				if (strcmp(oid, LDAP_NOTICE_OF_DISCONNECTION) == 0) {
					WARN("ldap: Notice of Disconnection (OID: %s)\n", oid);
				} else {
					WARN("ldap: Unsolicited message received. OID: %s\n", oid);
				}
				ldap_memfree(oid);
			}
			if (data != NULL) {
				WARN("ldap: Unsolicited message data: %.*s\n",
					 (int)data->bv_len, data->bv_val);
				ber_bvfree(data);
			}
		}
	}

	ret = ldap_parse_result(lcon->con, resmsg, &err, NULL, &err_desc, NULL, NULL, 0);
	if (ret != LDAP_SUCCESS) {
		ERR("ldap: Error while reading result status: %s\n",
			ldap_err2string(ret));
		goto error;
	}

	if (err != LDAP_SUCCESS) {
		ERR("ldap: LDAP server reports error: %s\n", ldap_err2string(err));
		goto error;
	}

	if (res) {
		lres = DB_GET_PAYLOAD(res);
		lres->msg = resmsg;
	} else if (resmsg) {
		ldap_msgfree(resmsg);
	}

	if (filter) pkg_free(filter);
	if (err_desc) ldap_memfree(err_desc);
	return 0;

 error:
	if (filter) pkg_free(filter);
	if (resmsg) ldap_msgfree(resmsg);
	if (err_desc) ldap_memfree(err_desc);
	return -1;
}
Пример #21
0
static int
do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr,
	int maxloop, int force, int chaserefs, int noinit, int delay,
	int action_type, void *action )
{
	LDAP	*ld = NULL;
	int  	i = 0;
	int     rc = LDAP_SUCCESS;
	ber_int_t msgid;
	LDAPMessage *res, *msg;
	char **dns = NULL;
	struct berval *creds = NULL;
	char *attrs[] = { LDAP_NO_ATTRS, NULL };
	int ndns = 0;
#ifdef _WIN32
	DWORD beg, end;
#else
	struct timeval beg, end;
#endif
	int version = LDAP_VERSION3;
	char *nullstr = "";

	ldap_initialize( &ld, uri );
	if ( ld == NULL ) {
		tester_perror( "ldap_initialize", NULL );
		exit( EXIT_FAILURE );
	}

	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
		chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );

	rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
	if ( rc != LDAP_SUCCESS ) {
		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
		exit( EXIT_FAILURE );
	}

	fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
			(long) pid, maxloop, base, filter, pwattr );

	if ( pwattr != NULL ) {
		attrs[ 0 ] = pwattr;
	}
	rc = ldap_search_ext( ld, base, LDAP_SCOPE_SUBTREE,
			filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
	if ( rc != LDAP_SUCCESS ) {
		tester_ldap_error( ld, "ldap_search_ext", NULL );
		exit( EXIT_FAILURE );
	}

	while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 )
	{
		BerElement *ber;
		struct berval bv;
		int done = 0;

		for ( msg = ldap_first_message( ld, res ); msg;
			msg = ldap_next_message( ld, msg ) )
		{
			switch ( ldap_msgtype( msg ) ) {
			case LDAP_RES_SEARCH_ENTRY:
				rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
				dns = realloc( dns, (ndns + 1)*sizeof(char *) );
				dns[ndns] = ber_strdup( bv.bv_val );
				if ( pwattr != NULL ) {
					struct berval	**values = ldap_get_values_len( ld, msg, pwattr );

					creds = realloc( creds, (ndns + 1)*sizeof(struct berval) );
					if ( values == NULL ) {
novals:;
						creds[ndns].bv_len = 0;
						creds[ndns].bv_val = nullstr;

					} else {
						static struct berval	cleartext = BER_BVC( "{CLEARTEXT} " );
						struct berval		value = *values[ 0 ];

						if ( value.bv_val[ 0 ] == '{' ) {
							char *end = ber_bvchr( &value, '}' );

							if ( end ) {
								if ( ber_bvcmp( &value, &cleartext ) == 0 ) {
									value.bv_val += cleartext.bv_len;
									value.bv_len -= cleartext.bv_len;

								} else {
									ldap_value_free_len( values );
									goto novals;
								}
							}

						}

						ber_dupbv( &creds[ndns], &value );
						ldap_value_free_len( values );
					}
				}
				ndns++;
				ber_free( ber, 0 );
				break;

			case LDAP_RES_SEARCH_RESULT:
				done = 1;
				break;
			}
			if ( done )
				break;
		}
		ldap_msgfree( res );
		if ( done ) break;
	}

#ifdef _WIN32
	beg = GetTickCount();
#else
	gettimeofday( &beg, NULL );
#endif

	if ( ndns == 0 ) {
		tester_error( "No DNs" );
		return 1;
	}

	fprintf( stderr, "  PID=%ld - Bind base=\"%s\" filter=\"%s\" got %d values.\n",
		(long) pid, base, filter, ndns );

	/* Ok, got list of DNs, now start binding to each */
	for ( i = 0; i < maxloop; i++ ) {
		int		j;
		struct berval	cred = { 0, NULL };


#if 0	/* use high-order bits for better randomness (Numerical Recipes in "C") */
		j = rand() % ndns;
#endif
		j = ((double)ndns)*rand()/(RAND_MAX + 1.0);

		if ( creds && !BER_BVISEMPTY( &creds[j] ) ) {
			cred = creds[j];
		}

		if ( do_bind( uri, dns[j], &cred, 1, force, chaserefs, noinit, &ld,
			action_type, action ) && !force )
		{
			break;
		}

		if ( delay ) {
			sleep( delay );
		}
	}

	if ( ld != NULL ) {
		ldap_unbind_ext( ld, NULL, NULL );
		ld = NULL;
	}

#ifdef _WIN32
	end = GetTickCount();
	end -= beg;

	fprintf( stderr, "  PID=%ld - Bind done %d in %d.%03d seconds.\n",
		(long) pid, i, end / 1000, end % 1000 );
#else
	gettimeofday( &end, NULL );
	end.tv_usec -= beg.tv_usec;
	if (end.tv_usec < 0 ) {
		end.tv_usec += 1000000;
		end.tv_sec -= 1;
	}
	end.tv_sec -= beg.tv_sec;

	fprintf( stderr, "  PID=%ld - Bind done %d in %ld.%06ld seconds.\n",
		(long) pid, i, (long) end.tv_sec, (long) end.tv_usec );
#endif

	if ( dns ) {
		for ( i = 0; i < ndns; i++ ) {
			ber_memfree( dns[i] );
		}
		free( dns );
	}

	if ( creds ) {
		for ( i = 0; i < ndns; i++ ) {
			if ( creds[i].bv_val != nullstr ) {
				ber_memfree( creds[i].bv_val );
			}
		}
		free( creds );
	}

	return 0;
}
Пример #22
0
extern "C" std::string
getRecipient(void * vh, Source * source)

{
	ldap_handle * h = (ldap_handle *) vh;
	int msgtype;
	int code;
	int rc;
	struct berval bv;
	std::string result;

	if (!h)
		return "";

	for (;;) {
		if (h->value && h->value->bv_val) {
			result = std::string(h->value->bv_val,
			    h->value->bv_len);
			h->value++;

			if (result.length() > 5 &&
			    !strncasecmp(result.c_str(), "smtp:", 5))
				result = result.substr(5);

			if (result.find_first_not_of(mailchars) !=
			    std::string::npos)
				continue;

			return result;
			}

		if (h->ber) {
			rc = ldap_get_attribute_ber(h->ldap, h->msg, h->ber,
			    &bv, &h->values);
			h->value = h->values;

			if (rc == LDAP_SUCCESS && bv.bv_val)
				continue;
			}

		h->release_message();

		rc = ldap_result(h->ldap,
		    LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &h->msg);

		if (!h->msg)
			throw ldap_error(rc);

		msgtype = ldap_msgtype(h->msg);

		switch (msgtype) {

		case LDAP_RES_SEARCH_RESULT:
			rc = ldap_parse_result(h->ldap, h->msg, &code,
			    NULL, NULL, NULL, NULL, 0);

			if (rc != LDAP_SUCCESS)
				throw ldap_error(rc);

			if (code != LDAP_SUCCESS)
				throw ldap_error(code);

			return "";

		case LDAP_RES_SEARCH_ENTRY:
			break;

		default:
			continue;
			}

		rc = ldap_get_dn_ber(h->ldap, h->msg, &h->ber, &bv);

		if (rc != LDAP_SUCCESS)
			throw ldap_error(rc);
		}

	return "";
}
Пример #23
0
/** Perform basic parsing of multiple types of messages, checking for error conditions
 *
 * @note Error messages should be retrieved with fr_strerror() and fr_strerror_pop()
 *
 * @param[out] ctrls	Server ctrls returned to the client.  May be NULL if not required.
 *			Must be freed with ldap_free_ctrls.
 * @param[in] conn	the message was received on.
 * @param[in] msg	we're parsing.
 * @param[in] dn	if processing the result from a search request.
 * @return One of the LDAP_PROC_* (#fr_ldap_rcode_t) values.
 */
fr_ldap_rcode_t fr_ldap_error_check(LDAPControl ***ctrls, fr_ldap_connection_t const *conn, LDAPMessage *msg, char const *dn)
{
	fr_ldap_rcode_t status = LDAP_PROC_SUCCESS;

	int msg_type;
	int lib_errno = LDAP_SUCCESS;	/* errno returned by the library */
	int srv_errno = LDAP_SUCCESS;	/* errno in the result message */

	char *part_dn = NULL;		/* Partial DN match */
	char *srv_err = NULL;		/* Server's extended error message */

	ssize_t len;

	if (ctrls) *ctrls = NULL;

	if (!msg) {
		ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
		if (lib_errno != LDAP_SUCCESS) goto process_error;

		fr_strerror_printf("No result available");
		return LDAP_PROC_NO_RESULT;
	}

	msg_type = ldap_msgtype(msg);
	switch (msg_type) {
	/*
	 *	Parse the result and check for errors sent by the server
	 */
	case LDAP_RES_SEARCH_RESULT:	/* The result of a search */
	case LDAP_RES_BIND:		/* The result of a bind operation */
	case LDAP_RES_EXTENDED:
		lib_errno = ldap_parse_result(conn->handle, msg,
					      &srv_errno, &part_dn, &srv_err,
					      NULL, ctrls, 0);
		break;

	/*
	 *	These are messages containing objects so unless they're
	 *	malformed they can't contain errors.
	 */
	case LDAP_RES_SEARCH_ENTRY:
		if (ctrls) lib_errno = ldap_get_entry_controls(conn->handle, msg, ctrls);
		break;

	/*
	 *	An intermediate message updating us on the result of an operation
	 */
	case LDAP_RES_INTERMEDIATE:
		lib_errno = ldap_parse_intermediate(conn->handle, msg, NULL, NULL, ctrls, 0);
		break;

	/*
	 *	Can't extract any more useful information.
	 */
	default:
		return LDAP_PROC_SUCCESS;
	}

	/*
	 *	Stupid messy API
	 */
	if (lib_errno != LDAP_SUCCESS) {
		rad_assert(!ctrls || !*ctrls);
		ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno);
	}

process_error:
	if ((lib_errno == LDAP_SUCCESS) && (srv_errno != LDAP_SUCCESS)) {
		lib_errno = srv_errno;
	} else if ((lib_errno != LDAP_SUCCESS) && (srv_errno == LDAP_SUCCESS)) {
		srv_errno = lib_errno;
	}

	switch (lib_errno) {
	case LDAP_SUCCESS:
		fr_strerror_printf("Success");
		break;

	case LDAP_SASL_BIND_IN_PROGRESS:
		fr_strerror_printf("Continuing");
		status = LDAP_PROC_CONTINUE;
		break;

	case LDAP_NO_SUCH_OBJECT:
		fr_strerror_printf("The specified DN wasn't found");
		status = LDAP_PROC_BAD_DN;

		/*
		 *	Build our own internal diagnostic string
		 */
		if (dn && part_dn) {
			char *spaces;
			char *text;

			len = fr_ldap_common_dn(dn, part_dn);
			if (len < 0) break;

			fr_canonicalize_error(NULL, &spaces, &text, -len, dn);
			fr_strerror_printf_push("%s", text);
			fr_strerror_printf_push("%s^ %s", spaces, "match stopped here");

			talloc_free(spaces);
			talloc_free(text);
		}
		goto error_string;

	case LDAP_INSUFFICIENT_ACCESS:
		fr_strerror_printf("Insufficient access. Check the identity and password configuration directives");
		status = LDAP_PROC_NOT_PERMITTED;
		break;

	case LDAP_UNWILLING_TO_PERFORM:
		fr_strerror_printf("Server was unwilling to perform");
		status = LDAP_PROC_NOT_PERMITTED;
		break;

	case LDAP_FILTER_ERROR:
		fr_strerror_printf("Bad search filter");
		status = LDAP_PROC_ERROR;
		break;

	case LDAP_TIMEOUT:
		fr_strerror_printf("Timed out while waiting for server to respond");
		status = LDAP_PROC_TIMEOUT;
		break;

	case LDAP_TIMELIMIT_EXCEEDED:
		fr_strerror_printf("Time limit exceeded");
		status = LDAP_PROC_TIMEOUT;
		break;

	case LDAP_BUSY:
	case LDAP_UNAVAILABLE:
	case LDAP_SERVER_DOWN:
		status = LDAP_PROC_BAD_CONN;
		goto error_string;

	case LDAP_INVALID_CREDENTIALS:
	case LDAP_CONSTRAINT_VIOLATION:
		status = LDAP_PROC_REJECT;
		goto error_string;

	case LDAP_OPERATIONS_ERROR:
		fr_strerror_printf("Please set 'chase_referrals=yes' and 'rebind=yes'. "
				   "See the ldap module configuration for details");

		/* FALL-THROUGH */
	default:
		status = LDAP_PROC_ERROR;

	error_string:
		if (lib_errno == srv_errno) {
			fr_strerror_printf("lib error: %s (%u)", ldap_err2string(lib_errno), lib_errno);
		} else {
			fr_strerror_printf("lib error: %s (%u), srv error: %s (%u)",
					   ldap_err2string(lib_errno), lib_errno,
					   ldap_err2string(srv_errno), srv_errno);
		}

		if (srv_err) fr_strerror_printf_push("Server said: %s", srv_err);

		break;
	}

	/*
	 *	Cleanup memory
	 */
	if (srv_err) ldap_memfree(srv_err);
	if (part_dn) ldap_memfree(part_dn);

	return status;
}
Пример #24
0
static int
ldap_connection_connect_parse(struct ldap_connection *conn,
			      struct ldap_op_queue_entry *req,
			      LDAPMessage *message, bool *finished_r)
{
	int ret, result_err;
	char *retoid, *result_errmsg;
	int msgtype = ldap_msgtype(message);

	*finished_r = TRUE;
	ret = ldap_parse_result(conn->conn, message, &result_err, NULL,
		&result_errmsg, NULL, NULL, 0);

	switch(conn->state) {
	case LDAP_STATE_TLS:
		if (msgtype != LDAP_RES_EXTENDED) {
			*finished_r = FALSE;
			return LDAP_SUCCESS;
		}
		if (ret != 0) {
			ldap_connection_result_failure(conn, req, ret, t_strdup_printf(
				"ldap_start_tls(uri=%s) failed: %s",
				conn->set.uri, ldap_err2string(ret)));
			return ret;
		} else if (result_err != 0) {
			if (conn->set.require_ssl) {
				ldap_connection_result_failure(conn, req, result_err, t_strdup_printf(
					"ldap_start_tls(uri=%s) failed: %s",
					conn->set.uri, result_errmsg));
				ldap_memfree(result_errmsg);
				return LDAP_INVALID_CREDENTIALS; /* make sure it disconnects */
			}
		} else {
			ret = ldap_parse_extended_result(conn->conn, message, &retoid, NULL, 0);
			/* retoid can be NULL even if ret == 0 */
			if (ret == 0) {
				ret = ldap_install_tls(conn->conn);
				if (ret != 0) {
					// if this fails we have to abort
					ldap_connection_result_failure(conn, req, ret, t_strdup_printf(
						"ldap_start_tls(uri=%s) failed: %s",
						conn->set.uri, ldap_err2string(ret)));
					return LDAP_INVALID_CREDENTIALS;
				}
			}
			if (ret != LDAP_SUCCESS) {
				if (conn->set.require_ssl) {
					ldap_connection_result_failure(conn, req, ret, t_strdup_printf(
						"ldap_start_tls(uri=%s) failed: %s",
						conn->set.uri, ldap_err2string(ret)));
					return LDAP_UNAVAILABLE;
				}
			} else {
				if (conn->set.debug > 0)
					i_debug("Using TLS connection to remote LDAP server");
			}
			ldap_memfree(retoid);
		}
		conn->state = LDAP_STATE_AUTH;
		return ldap_connect_next_message(conn, req, finished_r);
	case LDAP_STATE_AUTH:
		if (ret != LDAP_SUCCESS) {
			ldap_connection_result_failure(conn, req, ret, t_strdup_printf(
				"ldap_parse_result() failed for connect: %s",
				ldap_err2string(ret)));
			return ret;
		}
		if (result_err != LDAP_SUCCESS) {
			const char *error = result_errmsg != NULL ?
				result_errmsg : ldap_err2string(result_err);
				ldap_connection_result_failure(conn, req, result_err, t_strdup_printf(
				"Connect failed: %s", error));
			ldap_memfree(result_errmsg);
			return result_err;
		}
		if (msgtype != LDAP_RES_BIND) return 0;
		ret = ldap_parse_sasl_bind_result(conn->conn, message, &(conn->scred), 0);
		if (ret != LDAP_SUCCESS) {
			const char *error = t_strdup_printf(
				"Cannot bind with server: %s", ldap_err2string(ret));
			ldap_connection_result_failure(conn, req, ret, error);
			return 1;
		}
		conn->state = LDAP_STATE_CONNECT;
		return ldap_connect_next_message(conn, req, finished_r);
	default:
		i_unreached();
	}
	return LDAP_SUCCESS;
}
Пример #25
0
void
OPENLDAP::Book::refresh_result ()
{
  int result = LDAP_SUCCESS;
  int nbr = 0;
  struct timeval timeout = { 1, 0}; /* block 1s */
  LDAPMessage *msg_entry = NULL;
  LDAPMessage *msg_result = NULL;
  gchar* c_status = NULL;

  result = ldap_result (ldap_context, LDAP_RES_ANY, LDAP_MSG_ALL,
			&timeout, &msg_entry);


  if (result <= 0) {

    if (patience == 3) {

      patience--;
      Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this),
				   12);
    } else if (patience == 2) {

      patience--;
      Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this),
				   21);
    } else if (patience == 1) {

      patience--;
      Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this),
				   30);
    } else { // patience == 0

      status = std::string (_("Could not search"));
      updated (this->shared_from_this ());

      ldap_unbind_ext (ldap_context, NULL, NULL);
      ldap_context = NULL;
    }

    if (msg_entry != NULL)
      ldap_msgfree (msg_entry);

    return;
  }

  msg_result = ldap_first_message (ldap_context, msg_entry);
  do {

    if (ldap_msgtype (msg_result) == LDAP_RES_SEARCH_ENTRY) {

      ContactPtr contact = parse_result (msg_result);
      if (contact) {
	add_contact (contact);
        nbr++;
      }
    }
    msg_result = ldap_next_message (ldap_context, msg_result);
  } while (msg_result != NULL);

  // Do not count ekiga.net's first entry "Search Results ... 100 entries"
  if (bookinfo.uri_host == EKIGA_NET_URI)
    nbr--;
  c_status = g_strdup_printf (ngettext ("%d user found",
					"%d users found", nbr), nbr);
  status = c_status;
  g_free (c_status);

  updated (this->shared_from_this ());

  (void)ldap_msgfree (msg_entry);

  ldap_unbind_ext (ldap_context, NULL, NULL);
  ldap_context = NULL;
}
Пример #26
0
static void linphone_ldap_contact_provider_handle_search_result( LinphoneLDAPContactProvider* obj, LinphoneLDAPContactSearch* req, LDAPMessage* message )
{
	int msgtype = ldap_msgtype(message);

	switch(msgtype){

	case LDAP_RES_SEARCH_ENTRY:
	case LDAP_RES_EXTENDED:
	{
		LDAPMessage *entry = ldap_first_entry(obj->ld, message);
		LinphoneCore*   lc = LINPHONE_CONTACT_PROVIDER(obj)->lc;

		while( entry != NULL ){

			struct LDAPFriendData ldap_data = {0};
			bool_t contact_complete = FALSE;
			BerElement*  ber = NULL;
			char*       attr = ldap_first_attribute(obj->ld, entry, &ber);

			while( attr ){
				struct berval** values = ldap_get_values_len(obj->ld, entry, attr);
				struct berval**     it = values;

				while( values && *it && (*it)->bv_val && (*it)->bv_len )
				{
					contact_complete = linphone_ldap_contact_provider_complete_contact(obj, &ldap_data, attr, (*it)->bv_val);
					if( contact_complete ) break;

					it++;
				}

				if( values ) ldap_value_free_len(values);
				ldap_memfree(attr);

				if( contact_complete ) break;

				attr = ldap_next_attribute(obj->ld, entry, ber);
			}

			if( contact_complete ) {
				LinphoneAddress* la = linphone_core_interpret_url(lc, ldap_data.sip);
				if( la ){
					LinphoneFriend* lf = linphone_core_create_friend(lc);
					linphone_friend_set_address(lf, la);
					linphone_friend_set_name(lf, ldap_data.name);
					req->found_entries = ms_list_append(req->found_entries, lf);
					req->found_count++;
					//ms_message("Added friend %s / %s", ldap_data.name, ldap_data.sip);
					ms_free(ldap_data.sip);
					ms_free(ldap_data.name);
					linphone_address_destroy(la);
				}
			}

			if( ber ) ber_free(ber, 0);

			entry = ldap_next_entry(obj->ld, entry);
		}
	}
	break;

	case LDAP_RES_SEARCH_RESULT:
	{
		// this one is received when a request is finished
		req->complete = TRUE;
		linphone_contact_search_invoke_cb(LINPHONE_CONTACT_SEARCH(req), req->found_entries);
	}
	break;


	default: ms_message("[LDAP] Unhandled message type %x", msgtype); break;
	}
}
Пример #27
0
/*
 * always protected by conn_mutex
 * optionally protected by req_mutex and res_mutex
 */
LDAPConn *
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
	int connect, LDAPreqinfo *bind, int m_req, int m_res )
{
	LDAPConn	*lc;
	int		async = 0;

	LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
	Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
		use_ldsb, connect, (bind != NULL) );
	/*
	 * make a new LDAP server connection
	 * XXX open connection synchronously for now
	 */
	lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) );
	if ( lc == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( NULL );
	}
	
	if ( use_ldsb ) {
		assert( ld->ld_sb != NULL );
		lc->lconn_sb = ld->ld_sb;

	} else {
		lc->lconn_sb = ber_sockbuf_alloc();
		if ( lc->lconn_sb == NULL ) {
			LDAP_FREE( (char *)lc );
			ld->ld_errno = LDAP_NO_MEMORY;
			return( NULL );
		}
	}

	if ( connect ) {
		LDAPURLDesc	**srvp, *srv = NULL;

		async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );

		for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
			int		rc;

			rc = ldap_int_open_connection( ld, lc, *srvp, async );
			if ( rc != -1 ) {
				srv = *srvp;

				if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) {
					ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
				}

				break;
			}
		}

		if ( srv == NULL ) {
			if ( !use_ldsb ) {
				ber_sockbuf_free( lc->lconn_sb );
			}
			LDAP_FREE( (char *)lc );
			ld->ld_errno = LDAP_SERVER_DOWN;
			return( NULL );
		}

		lc->lconn_server = ldap_url_dup( srv );
	}

	lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
	lc->lconn_next = ld->ld_conns;
	ld->ld_conns = lc;

	if ( connect ) {
#ifdef HAVE_TLS
		if ( lc->lconn_server->lud_exts ) {
			int rc, ext = find_tls_ext( lc->lconn_server );
			if ( ext ) {
				LDAPConn	*savedefconn;

				savedefconn = ld->ld_defconn;
				++lc->lconn_refcnt;	/* avoid premature free */
				ld->ld_defconn = lc;

				LDAP_REQ_UNLOCK_IF(m_req);
				LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
				LDAP_RES_UNLOCK_IF(m_res);
				rc = ldap_start_tls_s( ld, NULL, NULL );
				LDAP_RES_LOCK_IF(m_res);
				LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
				LDAP_REQ_LOCK_IF(m_req);
				ld->ld_defconn = savedefconn;
				--lc->lconn_refcnt;

				if ( rc != LDAP_SUCCESS && ext == 2 ) {
					ldap_free_connection( ld, lc, 1, 0 );
					return NULL;
				}
			}
		}
#endif
	}

	if ( bind != NULL ) {
		int		err = 0;
		LDAPConn	*savedefconn;

		/* Set flag to prevent additional referrals
		 * from being processed on this
		 * connection until the bind has completed
		 */
		lc->lconn_rebind_inprogress = 1;
		/* V3 rebind function */
		if ( ld->ld_rebind_proc != NULL) {
			LDAPURLDesc	*srvfunc;

			srvfunc = ldap_url_dup( *srvlist );
			if ( srvfunc == NULL ) {
				ld->ld_errno = LDAP_NO_MEMORY;
				err = -1;
			} else {
				savedefconn = ld->ld_defconn;
				++lc->lconn_refcnt;	/* avoid premature free */
				ld->ld_defconn = lc;

				Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
				LDAP_REQ_UNLOCK_IF(m_req);
				LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
				LDAP_RES_UNLOCK_IF(m_res);
				err = (*ld->ld_rebind_proc)( ld,
					bind->ri_url, bind->ri_request, bind->ri_msgid,
					ld->ld_rebind_params );
				LDAP_RES_LOCK_IF(m_res);
				LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
				LDAP_REQ_LOCK_IF(m_req);

				ld->ld_defconn = savedefconn;
				--lc->lconn_refcnt;

				if ( err != 0 ) {
					err = -1;
					ldap_free_connection( ld, lc, 1, 0 );
					lc = NULL;
				}
				ldap_free_urldesc( srvfunc );
			}

		} else {
			int		msgid, rc;
			struct berval	passwd = BER_BVNULL;

			savedefconn = ld->ld_defconn;
			++lc->lconn_refcnt;	/* avoid premature free */
			ld->ld_defconn = lc;

			Debug( LDAP_DEBUG_TRACE,
				"anonymous rebind via ldap_sasl_bind(\"\")\n",
				0, 0, 0);

			LDAP_REQ_UNLOCK_IF(m_req);
			LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
			LDAP_RES_UNLOCK_IF(m_res);
			rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
				NULL, NULL, &msgid );
			if ( rc != LDAP_SUCCESS ) {
				err = -1;

			} else {
				for ( err = 1; err > 0; ) {
					struct timeval	tv = { 0, 100000 };
					LDAPMessage	*res = NULL;

					switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) {
					case -1:
						err = -1;
						break;

					case 0:
#ifdef LDAP_R_COMPILE
						ldap_pvt_thread_yield();
#endif
						break;

					case LDAP_RES_BIND:
						rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 );
						if ( rc != LDAP_SUCCESS ) {
							err = -1;

						} else if ( err != LDAP_SUCCESS ) {
							err = -1;
						}
						/* else err == LDAP_SUCCESS == 0 */
						break;

					default:
						Debug( LDAP_DEBUG_TRACE,
							"ldap_new_connection %p: "
							"unexpected response %d "
							"from BIND request id=%d\n",
							(void *) ld, ldap_msgtype( res ), msgid );
						err = -1;
						break;
					}
				}
			}
			LDAP_RES_LOCK_IF(m_res);
			LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
			LDAP_REQ_LOCK_IF(m_req);
			ld->ld_defconn = savedefconn;
			--lc->lconn_refcnt;

			if ( err != 0 ) {
				ldap_free_connection( ld, lc, 1, 0 );
				lc = NULL;
			}
		}
		if ( lc != NULL )
			lc->lconn_rebind_inprogress = 0;
	}
	return( lc );
}
Пример #28
0
static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
                         size_t len, CURLcode *err)
{
  ldapconninfo *li = conn->proto.generic;
  struct SessionHandle *data = conn->data;
  ldapreqinfo *lr = data->req.protop;
  int rc, ret;
  LDAPMessage *msg = NULL;
  LDAPMessage *ent;
  BerElement *ber = NULL;
  struct timeval tv = {0, 1};

  (void)len;
  (void)buf;
  (void)sockindex;

  rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg);
  if(rc < 0) {
    failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
    *err = CURLE_RECV_ERROR;
    return -1;
  }

  *err = CURLE_AGAIN;
  ret = -1;

  /* timed out */
  if(!msg)
    return ret;

  for(ent = ldap_first_message(li->ld, msg); ent;
    ent = ldap_next_message(li->ld, ent)) {
    struct berval bv, *bvals, **bvp = &bvals;
    int binary = 0, msgtype;

    msgtype = ldap_msgtype(ent);
    if(msgtype == LDAP_RES_SEARCH_RESULT) {
      int code;
      char *info = NULL;
      rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
      if(rc) {
        failf(data, "LDAP local: search ldap_parse_result %s",
              ldap_err2string(rc));
        *err = CURLE_LDAP_SEARCH_FAILED;
      }
      else if(code && code != LDAP_SIZELIMIT_EXCEEDED) {
        failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
              info ? info : "");
        *err = CURLE_LDAP_SEARCH_FAILED;
      }
      else {
        /* successful */
        if(code == LDAP_SIZELIMIT_EXCEEDED)
          infof(data, "There are more than %d entries\n", lr->nument);
        data->req.size = data->req.bytecount;
        *err = CURLE_OK;
        ret = 0;
      }
      lr->msgid = 0;
      ldap_memfree(info);
      break;
    }
    else if(msgtype != LDAP_RES_SEARCH_ENTRY)
      continue;

    lr->nument++;
    rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
    if(rc < 0) {
      /* TODO: verify that this is really how this return code should be
         handled */
      *err = CURLE_RECV_ERROR;
      return -1;
    }
    *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
    if(*err)
      return -1;

    *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
                             bv.bv_len);
    if(*err)
      return -1;

    *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
    if(*err)
      return -1;
    data->req.bytecount += bv.bv_len + 5;

    for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
      rc == LDAP_SUCCESS;
      rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
      int i;

      if(bv.bv_val == NULL) break;

      if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
        binary = 1;
      else
        binary = 0;

      for(i=0; bvals[i].bv_val != NULL; i++) {
        int binval = 0;
        *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
        if(*err)
          return -1;

        *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
                                 bv.bv_len);
        if(*err)
          return -1;

        *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
        if(*err)
          return -1;
        data->req.bytecount += bv.bv_len + 2;

        if(!binary) {
          /* check for leading or trailing whitespace */
          if(ISSPACE(bvals[i].bv_val[0]) ||
              ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
            binval = 1;
          else {
            /* check for unprintable characters */
            unsigned int j;
            for(j=0; j<bvals[i].bv_len; j++)
              if(!ISPRINT(bvals[i].bv_val[j])) {
                binval = 1;
                break;
              }
          }
        }
        if(binary || binval) {
          char *val_b64 = NULL;
          size_t val_b64_sz = 0;
          /* Binary value, encode to base64. */
          CURLcode error = Curl_base64_encode(data,
                                              bvals[i].bv_val,
                                              bvals[i].bv_len,
                                              &val_b64,
                                              &val_b64_sz);
          if(error) {
            ber_memfree(bvals);
            ber_free(ber, 0);
            ldap_msgfree(msg);
            *err = error;
            return -1;
          }
          *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
          if(*err)
            return -1;

          data->req.bytecount += 2;
          if(val_b64_sz > 0) {
            *err = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
                                     val_b64_sz);
            if(*err)
              return -1;
            free(val_b64);
            data->req.bytecount += val_b64_sz;
          }
        }
        else {
          *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
          if(*err)
            return -1;

          *err = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
                                   bvals[i].bv_len);
          if(*err)
            return -1;

          data->req.bytecount += bvals[i].bv_len + 1;
        }
        *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
        if(*err)
          return -1;

        data->req.bytecount++;
      }
      ber_memfree(bvals);
      *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
      if(*err)
        return -1;
      data->req.bytecount++;
    }
    *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
    if(*err)
      return -1;
    data->req.bytecount++;
    ber_free(ber, 0);
  }
  ldap_msgfree(msg);
  return ret;
}
Пример #29
0
static int process_response(
	LDAP *ld,
	int msgid,
	int op,
	const char *dn )
{
	LDAPMessage	*res;
	int		rc = LDAP_OTHER, msgtype;
	struct timeval	tv = { 0, 0 };
	int		err;
	char		*text = NULL, *matched = NULL, **refs = NULL;
	LDAPControl	**ctrls = NULL;

	for ( ; ; ) {
		tv.tv_sec = 0;
		tv.tv_usec = 100000;

		rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res );
		if ( tool_check_abandon( ld, msgid ) ) {
			return LDAP_CANCELLED;
		}

		if ( rc == -1 ) {
			ldap_get_option( ld, LDAP_OPT_RESULT_CODE, &rc );
			tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
			return rc;
		}

		if ( rc != 0 ) {
			break;
		}
	}

	msgtype = ldap_msgtype( res );

	rc = ldap_parse_result( ld, res, &err, &matched, &text, &refs, &ctrls, 1 );
	if ( rc == LDAP_SUCCESS ) rc = err;

#ifdef LDAP_X_TXN
	if ( rc == LDAP_X_TXN_SPECIFY_OKAY ) {
		rc = LDAP_SUCCESS;
	} else
#endif
	if ( rc != LDAP_SUCCESS ) {
		tool_perror( res2str( op ), rc, NULL, matched, text, refs );
	} else if ( msgtype != op ) {
		fprintf( stderr, "%s: msgtype: expected %d got %d\n",
			res2str( op ), op, msgtype );
		rc = LDAP_OTHER;
	}

	if ( text ) ldap_memfree( text );
	if ( matched ) ldap_memfree( matched );
	if ( text ) ber_memvfree( (void **)refs );

	if ( ctrls ) {
		tool_print_ctrls( ld, ctrls );
		ldap_controls_free( ctrls );
	}

	return rc;
}
Пример #30
0
/* return false if the request is still in progress
 * return true if the request is completed
 */
static bool lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)
{
	struct ldb_context *ldb;
	struct lldb_private *lldb = ac->lldb;
	LDAPControl **serverctrlsp = NULL;
	char **referralsp = NULL;
	char *matcheddnp = NULL;
	char *errmsgp = NULL;
	LDAPMessage *msg;
	int type;
	struct ldb_message *ldbmsg;
	char *referral;
	bool callback_failed;
	bool request_done;
	bool lret;
	unsigned int i;
	int ret;

	ldb = ldb_module_get_ctx(ac->module);

	type = ldap_msgtype(result);
	callback_failed = false;
	request_done = false;

	switch (type) {
	case LDAP_RES_SEARCH_ENTRY:

		msg = ldap_first_entry(lldb->ldap, result);
	       	if (msg != NULL) {
			BerElement *berptr = NULL;
			char *attr, *dn;

			ldbmsg = ldb_msg_new(ac);
			if (!ldbmsg) {
				ldb_oom(ldb);
				ret = LDB_ERR_OPERATIONS_ERROR;
				break;
			}

			dn = ldap_get_dn(lldb->ldap, msg);
			if (!dn) {
				ldb_oom(ldb);
				talloc_free(ldbmsg);
				ret = LDB_ERR_OPERATIONS_ERROR;
				break;
			}
			ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, dn);
			if ( ! ldb_dn_validate(ldbmsg->dn)) {
				ldb_asprintf_errstring(ldb, "Invalid DN '%s' in reply", dn);
				talloc_free(ldbmsg);
				ret = LDB_ERR_OPERATIONS_ERROR;
				ldap_memfree(dn);
				break;
			}
			ldap_memfree(dn);

			ldbmsg->num_elements = 0;
			ldbmsg->elements = NULL;

			/* loop over all attributes */
			for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
			     attr;
			     attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
				struct berval **bval;
				bval = ldap_get_values_len(lldb->ldap, msg, attr);

				if (bval) {
					lldb_add_msg_attr(ldb, ldbmsg, attr, bval);
					ldap_value_free_len(bval);
				}
			}
			if (berptr) ber_free(berptr, 0);

			ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */);
			if (ret != LDB_SUCCESS) {
				ldb_asprintf_errstring(ldb, "entry send failed: %s",
						       ldb_errstring(ldb));
				callback_failed = true;
			}
		} else {
			ret = LDB_ERR_OPERATIONS_ERROR;
		}
		break;

	case LDAP_RES_SEARCH_REFERENCE:

		ret = ldap_parse_reference(lldb->ldap, result,
					   &referralsp, &serverctrlsp, 0);
		if (ret != LDAP_SUCCESS) {
			ldb_asprintf_errstring(ldb, "ldap reference parse error: %s : %s",
					       ldap_err2string(ret), errmsgp);
			ret = LDB_ERR_OPERATIONS_ERROR;
			break;
		}
		if (referralsp == NULL) {
			ldb_asprintf_errstring(ldb, "empty ldap referrals list");
			ret = LDB_ERR_PROTOCOL_ERROR;
			break;
		}

		for (i = 0; referralsp[i]; i++) {
			referral = talloc_strdup(ac, referralsp[i]);

			ret = ldb_module_send_referral(ac->req, referral);
			if (ret != LDB_SUCCESS) {
				ldb_asprintf_errstring(ldb, "referral send failed: %s",
						       ldb_errstring(ldb));
				callback_failed = true;
				break;
			}
		}
		break;

	case LDAP_RES_SEARCH_RESULT:
	case LDAP_RES_MODIFY:
	case LDAP_RES_ADD:
	case LDAP_RES_DELETE:
	case LDAP_RES_MODDN:

		if (ldap_parse_result(lldb->ldap, result, &ret,
					&matcheddnp, &errmsgp,
					&referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
			ret = LDB_ERR_OPERATIONS_ERROR;
		}
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, "ldap parse error for type %d: %s : %s",
					       type, ldap_err2string(ret), errmsgp);
			break;
		}

		if (serverctrlsp != NULL) {
			/* FIXME: transform the LDAPControl list into an ldb_control one */
			ac->controls = NULL;
		}

		request_done = true;
		break;

	default:
		ldb_asprintf_errstring(ldb, "unknown ldap return type: %d", type);
		ret = LDB_ERR_PROTOCOL_ERROR;
		break;
	}

	if (ret != LDB_SUCCESS) {

		/* if the callback failed the caller will have freed the
		 * request. Just return and don't try to use it */
		if (callback_failed) {

			/* tell lldb_wait to remove the request from the
			 *  queue */
			lret = true;
			goto free_and_return;
		}

		request_done = true;
	}

	if (request_done) {
		lldb_request_done(ac, ac->controls, ret);
		lret = true;
		goto free_and_return;
	}

	lret = false;

free_and_return:

	if (matcheddnp) ldap_memfree(matcheddnp);
	if (errmsgp && *errmsgp) {
		ldb_set_errstring(ldb, errmsgp);
	}
	if (errmsgp) {
		ldap_memfree(errmsgp);
	}
	if (referralsp) ldap_value_free(referralsp);
	if (serverctrlsp) ldap_controls_free(serverctrlsp);

	ldap_msgfree(result);

	return lret;
}