Exemple #1
0
static NTSTATUS tcp_ldap_rootdse(void *data,
				 TALLOC_CTX *mem_ctx,
				 struct cldap_search *io)
{
	struct ldap_connection *conn = talloc_get_type(data,
						       struct ldap_connection);
	struct ldap_message *msg, *result;
	struct ldap_request *req;
	int i;
	NTSTATUS status;

	msg = new_ldap_message(mem_ctx);
	if (!msg) {
		return NT_STATUS_NO_MEMORY;
	}

	msg->type = LDAP_TAG_SearchRequest;
	msg->r.SearchRequest.basedn = "";
	msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
	msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
	msg->r.SearchRequest.timelimit = 0;
	msg->r.SearchRequest.sizelimit = 0;
	msg->r.SearchRequest.attributesonly = false;
	msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter);
	msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes);
	msg->r.SearchRequest.attributes = io->in.attributes;

	req = ldap_request_send(conn, msg);
	if (req == NULL) {
		printf("Could not setup ldap search\n");
		return NT_STATUS_UNSUCCESSFUL;
	}

	ZERO_STRUCT(io->out);
	for (i = 0; i < 2; ++i) {
		status = ldap_result_n(req, i, &result);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
		switch (result->type) {
		case LDAP_TAG_SearchResultEntry:
			if (i != 0) {
				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
			}
			io->out.response = &result->r.SearchResultEntry;
			break;
		case LDAP_TAG_SearchResultDone:
			io->out.result = &result->r.SearchResultDone;
			if (io->out.result->resultcode != LDAP_SUCCESS) {
				return NT_STATUS_LDAP(io->out.result->resultcode);
			}

			return NT_STATUS_OK;
		default:
			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
		}
	}

	return NT_STATUS_OK;
}
Exemple #2
0
static struct ldap_message *new_ldap_sasl_bind_msg(struct ldap_connection *conn, 
						   const char *sasl_mechanism, 
						   DATA_BLOB *secblob)
{
	struct ldap_message *res;

	res = new_ldap_message(conn);
	if (!res) {
		return NULL;
	}

	res->type = LDAP_TAG_BindRequest;
	res->r.BindRequest.version = 3;
	res->r.BindRequest.dn = "";
	res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
	res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res, sasl_mechanism);
	if (secblob) {
		res->r.BindRequest.creds.SASL.secblob = talloc(res, DATA_BLOB);
		if (!res->r.BindRequest.creds.SASL.secblob) {
			talloc_free(res);
			return NULL;
		}
		*res->r.BindRequest.creds.SASL.secblob = *secblob;
	} else {
		res->r.BindRequest.creds.SASL.secblob = NULL;
	}
	res->controls = NULL;

	return res;
}
Exemple #3
0
static bool test_search_auth_empty_substring(struct ldap_connection *conn, const char *basedn)
{
	bool ret = true;
	struct ldap_message *msg, *result;
	struct ldap_request *req;
	NTSTATUS status;
	struct ldap_Result *r;

	printf("Testing authenticated base Search with objectclass= substring filter\n");

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	msg->type = LDAP_TAG_SearchRequest;
	msg->r.SearchRequest.basedn = basedn;
	msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
	msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
	msg->r.SearchRequest.timelimit = 0;
	msg->r.SearchRequest.sizelimit = 0;
	msg->r.SearchRequest.attributesonly = false;
	msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
	msg->r.SearchRequest.tree->operation = LDB_OP_SUBSTRING;
	msg->r.SearchRequest.tree->u.substring.attr = "objectclass";
	msg->r.SearchRequest.tree->u.substring.start_with_wildcard = 1;
	msg->r.SearchRequest.tree->u.substring.end_with_wildcard = 1;
	msg->r.SearchRequest.tree->u.substring.chunks = NULL;
	msg->r.SearchRequest.num_attributes = 0;
	msg->r.SearchRequest.attributes = NULL;

	req = ldap_request_send(conn, msg);
	if (req == NULL) {
		printf("Could not setup ldap search\n");
		return false;
	}

	status = ldap_result_one(req, &result, LDAP_TAG_SearchResultDone);
	if (!NT_STATUS_IS_OK(status)) {
		printf("looking for search result done failed - %s\n", nt_errstr(status));
		return false;
	}

	printf("received %d replies\n", req->num_replies);

	r = &result->r.SearchResultDone;

	if (r->resultcode != LDAP_SUCCESS) {
		printf("search result done gave error - %s\n", ldb_strerror(r->resultcode));
		return false;
	}

	return ret;
}
Exemple #4
0
static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn, 
						     const char *dn, const char *pw)
{
	struct ldap_message *res;

	res = new_ldap_message(conn);
	if (!res) {
		return NULL;
	}

	res->type = LDAP_TAG_BindRequest;
	res->r.BindRequest.version = 3;
	res->r.BindRequest.dn = talloc_strdup(res, dn);
	res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
	res->r.BindRequest.creds.password = talloc_strdup(res, pw);
	res->controls = NULL;

	return res;
}
Exemple #5
0
static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
{
	struct ldap_message *msg, *rep;
	struct ldap_request *req;
	const char *val;
	NTSTATUS status;

	printf("Testing SASL Compare: %s\n", basedn);

	if (!basedn) {
		return false;
	}

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	msg->type = LDAP_TAG_CompareRequest;
	msg->r.CompareRequest.dn = basedn;
	msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
	val = "domain";
	msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap compare request - %s\n", nt_errstr(status));
		return false;
	}

	DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
		rep->r.CompareResponse.resultcode,
		rep->r.CompareResponse.dn,
		rep->r.CompareResponse.errormessage,
		rep->r.CompareResponse.referral));

	return true;
}
Exemple #6
0
static bool test_abandon_request(struct torture_context *tctx,
	struct ldap_connection *conn, const char *basedn)
{
	struct ldap_message *msg;
	struct ldap_request *req;
	NTSTATUS status;

	printf("Testing the AbandonRequest with an old message id!\n");

	if (!basedn) {
		return false;
	}

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	printf(" Try a AbandonRequest for an old message id\n");

	msg->type = LDAP_TAG_AbandonRequest;
	msg->r.AbandonRequest.messageid = 1;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_request_wait(req);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap abandon request - %s\n", nt_errstr(status));
		return false;
	}

	return true;
}
Exemple #7
0
static bool test_search_rootDSE(struct ldap_connection *conn, const char **basedn,
	const char ***partitions)
{
	bool ret = true;
	struct ldap_message *msg, *result;
	struct ldap_request *req;
	int i;
	struct ldap_SearchResEntry *r;
	NTSTATUS status;

	printf("Testing RootDSE Search\n");

	*basedn = NULL;

	if (partitions != NULL) {
		*partitions = const_str_list(str_list_make_empty(conn));
	}

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	msg->type = LDAP_TAG_SearchRequest;
	msg->r.SearchRequest.basedn = "";
	msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
	msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
	msg->r.SearchRequest.timelimit = 0;
	msg->r.SearchRequest.sizelimit = 0;
	msg->r.SearchRequest.attributesonly = false;
	msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
	msg->r.SearchRequest.num_attributes = 0;
	msg->r.SearchRequest.attributes = NULL;

	req = ldap_request_send(conn, msg);
	if (req == NULL) {
		printf("Could not setup ldap search\n");
		return false;
	}

	status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
	if (!NT_STATUS_IS_OK(status)) {
		printf("search failed - %s\n", nt_errstr(status));
		return false;
	}

	printf("received %d replies\n", req->num_replies);

	r = &result->r.SearchResultEntry;
		
	DEBUG(1,("\tdn: %s\n", r->dn));
	for (i=0; i<r->num_attributes; i++) {
		int j;
		for (j=0; j<r->attributes[i].num_values; j++) {
			DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
				 (int)r->attributes[i].values[j].length,
				 (int)r->attributes[i].values[j].length,
				 (char *)r->attributes[i].values[j].data));
			if (!(*basedn) && 
			    strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
				*basedn = talloc_asprintf(conn, "%.*s",
							  (int)r->attributes[i].values[j].length,
							  (char *)r->attributes[i].values[j].data);
			}
			if ((partitions != NULL) &&
			    (strcasecmp("namingContexts", r->attributes[i].name) == 0)) {
				char *entry = talloc_asprintf(conn, "%.*s",
							      (int)r->attributes[i].values[j].length,
							      (char *)r->attributes[i].values[j].data);
				*partitions = str_list_add(*partitions, entry);
			}
		}
	}

	return ret;
}
Exemple #8
0
/* This has to be done using the LDAP API since the LDB API does only transmit
 * the error code and not the error message. */
static bool test_error_codes(struct torture_context *tctx,
	struct ldap_connection *conn, const char *basedn)
{
	struct ldap_message *msg, *rep;
	struct ldap_request *req;
	const char *err_code_str;
	char *endptr;
	WERROR err;
	NTSTATUS status;

	printf("Testing the most important error code -> error message conversions!\n");

	if (!basedn) {
		return false;
	}

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	printf(" Try a wrong addition\n");

	msg->type = LDAP_TAG_AddRequest;
	msg->r.AddRequest.dn = basedn;
	msg->r.AddRequest.num_attributes = 0;
	msg->r.AddRequest.attributes = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap add request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.AddResponse.resultcode == 0)
		|| (rep->r.AddResponse.errormessage == NULL)
		|| (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.AddResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
			|| (rep->r.AddResponse.resultcode != LDAP_REFERRAL)) {
			return false;
	}
	if ((rep->r.AddResponse.referral == NULL)
			|| (strstr(rep->r.AddResponse.referral, basedn) == NULL)) {
			return false;
	}

	printf(" Try another wrong addition\n");

	msg->type = LDAP_TAG_AddRequest;
	msg->r.AddRequest.dn = "";
	msg->r.AddRequest.num_attributes = 0;
	msg->r.AddRequest.attributes = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap add request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.AddResponse.resultcode == 0)
		|| (rep->r.AddResponse.errormessage == NULL)
		|| (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.AddResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_ROOT_MUST_BE_NC) &&
	     !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
		|| (rep->r.AddResponse.resultcode != LDAP_NAMING_VIOLATION)) {
		return false;
	}

	printf(" Try a wrong modification\n");

	msg->type = LDAP_TAG_ModifyRequest;
	msg->r.ModifyRequest.dn = basedn;
	msg->r.ModifyRequest.num_mods = 0;
	msg->r.ModifyRequest.mods = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap modifification request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyResponse.resultcode == 0)
		|| (rep->r.ModifyResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
	     !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
		|| (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
		return false;
	}

	printf(" Try another wrong modification\n");

	msg->type = LDAP_TAG_ModifyRequest;
	msg->r.ModifyRequest.dn = "";
	msg->r.ModifyRequest.num_mods = 0;
	msg->r.ModifyRequest.mods = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap modifification request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyResponse.resultcode == 0)
		|| (rep->r.ModifyResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
	     !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
		|| (rep->r.ModifyResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
		return false;
	}

	printf(" Try a wrong removal\n");

	msg->type = LDAP_TAG_DelRequest;
	msg->r.DelRequest.dn = basedn;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap removal request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.DelResponse.resultcode == 0)
		|| (rep->r.DelResponse.errormessage == NULL)
		|| (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.DelResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_CANT_DELETE) &&
	     !W_ERROR_EQUAL(err, WERR_DS_UNWILLING_TO_PERFORM))
		|| (rep->r.DelResponse.resultcode != LDAP_UNWILLING_TO_PERFORM)) {
		return false;
	}

	printf(" Try another wrong removal\n");

	msg->type = LDAP_TAG_DelRequest;
	msg->r.DelRequest.dn = "";

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap removal request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.DelResponse.resultcode == 0)
		|| (rep->r.DelResponse.errormessage == NULL)
		|| (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}
	
	err = ad_error(rep->r.DelResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
	     !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
		|| (rep->r.DelResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
		return false;
	}

	printf(" Try a wrong rename\n");

	msg->type = LDAP_TAG_ModifyDNRequest;
	msg->r.ModifyDNRequest.dn = basedn;
	msg->r.ModifyDNRequest.newrdn = "dc=test";
	msg->r.ModifyDNRequest.deleteolddn = true;
	msg->r.ModifyDNRequest.newsuperior = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap rename request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyDNResponse.resultcode == 0)
		|| (rep->r.ModifyDNResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_NO_PARENT_OBJECT) &&
	     !W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
		|| (rep->r.ModifyDNResponse.resultcode != LDAP_OTHER)) {
		return false;
	}

	printf(" Try another wrong rename\n");

	msg->type = LDAP_TAG_ModifyDNRequest;
	msg->r.ModifyDNRequest.dn = basedn;
	msg->r.ModifyDNRequest.newrdn = basedn;
	msg->r.ModifyDNRequest.deleteolddn = true;
	msg->r.ModifyDNRequest.newsuperior = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap rename request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyDNResponse.resultcode == 0)
		|| (rep->r.ModifyDNResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
	     !W_ERROR_EQUAL(err, WERR_DS_NAMING_VIOLATION))
		|| (rep->r.ModifyDNResponse.resultcode != LDAP_NAMING_VIOLATION)) {
		return false;
	}

	printf(" Try another wrong rename\n");

	msg->type = LDAP_TAG_ModifyDNRequest;
	msg->r.ModifyDNRequest.dn = basedn;
	msg->r.ModifyDNRequest.newrdn = "";
	msg->r.ModifyDNRequest.deleteolddn = true;
	msg->r.ModifyDNRequest.newsuperior = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap rename request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyDNResponse.resultcode == 0)
		|| (rep->r.ModifyDNResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAMETER) &&
	     !W_ERROR_EQUAL(err, WERR_DS_PROTOCOL_ERROR))
		|| (rep->r.ModifyDNResponse.resultcode != LDAP_PROTOCOL_ERROR)) {
		return false;
	}

	printf(" Try another wrong rename\n");

	msg->type = LDAP_TAG_ModifyDNRequest;
	msg->r.ModifyDNRequest.dn = "";
	msg->r.ModifyDNRequest.newrdn = "cn=temp";
	msg->r.ModifyDNRequest.deleteolddn = true;
	msg->r.ModifyDNRequest.newsuperior = NULL;

	req = ldap_request_send(conn, msg);
	if (!req) {
		return false;
	}

	status = ldap_result_one(req, &rep, LDAP_TAG_ModifyDNResponse);
	if (!NT_STATUS_IS_OK(status)) {
		printf("error in ldap rename request - %s\n", nt_errstr(status));
		return false;
	}

	if ((rep->r.ModifyDNResponse.resultcode == 0)
		|| (rep->r.ModifyDNResponse.errormessage == NULL)
		|| (strtol(rep->r.ModifyDNResponse.errormessage, &endptr,16) <= 0)
		|| (*endptr != ':')) {
		printf("Invalid error message!\n");
		return false;
	}

	err = ad_error(rep->r.ModifyDNResponse.errormessage, &endptr);
	err_code_str = win_errstr(err);
	printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
	if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND) &&
	     !W_ERROR_EQUAL(err, WERR_DS_NO_SUCH_OBJECT))
		|| (rep->r.ModifyDNResponse.resultcode != LDAP_NO_SUCH_OBJECT)) {
		return false;
	}

	return true;
}