Esempio n. 1
0
static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
{
	struct ldb_context *ldb;
	struct acl_context *ac;
	struct acl_private *data;
	struct ldb_result *acl_res;
	static const char *acl_attrs[] = {
		"objectClass",
		"nTSecurityDescriptor",
		"objectSid",
		NULL
	};
	int ret, i;

	ac = talloc_get_type(req->context, struct acl_context);
	data = talloc_get_type(ldb_module_get_private(ac->module), struct acl_private);
	ldb = ldb_module_get_ctx(ac->module);

	if (!ares) {
		return ldb_module_done(ac->req, NULL, NULL,
				       LDB_ERR_OPERATIONS_ERROR);
	}
	if (ares->error != LDB_SUCCESS) {
		return ldb_module_done(ac->req, ares->controls,
				       ares->response, ares->error);
	}

	switch (ares->type) {
	case LDB_REPLY_ENTRY:
		if (ac->allowedAttributes 
		    || ac->allowedChildClasses
		    || ac->allowedChildClassesEffective
		    || ac->allowedAttributesEffective
		    || ac->sDRightsEffective) {
			ret = ldb_search(ldb, ac, &acl_res, ares->message->dn, LDB_SCOPE_BASE, acl_attrs, NULL);
			if (ret != LDB_SUCCESS) {
				return ldb_module_done(ac->req, NULL, NULL, ret);
			}
			if (ac->allowedAttributes || ac->allowedAttributesEffective) {
				ret = acl_allowedAttributes(ac->module, acl_res->msgs[0], ares->message, ac);
				if (ret != LDB_SUCCESS) {
					return ldb_module_done(ac->req, NULL, NULL, ret);
				}
			}
			if (ac->allowedChildClasses) {
				ret = acl_childClasses(ac->module, acl_res->msgs[0],
						       ares->message, "allowedChildClasses");
				if (ret != LDB_SUCCESS) {
					return ldb_module_done(ac->req, NULL, NULL, ret);
				}
			}
			if (ac->allowedChildClassesEffective) {
				ret = acl_childClassesEffective(ac->module,
								acl_res->msgs[0], ares->message, ac);
				if (ret != LDB_SUCCESS) {
					return ldb_module_done(ac->req, NULL, NULL, ret);
				}
			}
			if (ac->sDRightsEffective) {
				ret = acl_sDRightsEffective(ac->module,
							    acl_res->msgs[0], ares->message, ac);
				if (ret != LDB_SUCCESS) {
					return ldb_module_done(ac->req, NULL, NULL, ret);
				}
			}
		}
		if (data && data->password_attrs) {
			if (ac->user_type != SECURITY_SYSTEM) {
				for (i = 0; data->password_attrs[i]; i++) {
					ldb_msg_remove_attr(ares->message, data->password_attrs[i]);
				}
			}
		}
		return ldb_module_send_entry(ac->req, ares->message, ares->controls);

	case LDB_REPLY_REFERRAL:
		return ldb_module_send_referral(ac->req, ares->referral);

	case LDB_REPLY_DONE:
		return ldb_module_done(ac->req, ares->controls,
				       ares->response, LDB_SUCCESS);

	}
	return LDB_SUCCESS;
}
Esempio n. 2
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;
}