📄 ldb_map.c
字号:
/* Build a request to search a record by its DN. */struct ldb_request *map_search_base_req(struct map_context *ac, struct ldb_dn *dn, const char * const *attrs, const struct ldb_parse_tree *tree, void *context, ldb_search_callback callback){ struct ldb_request *req; req = talloc_zero(ac, struct ldb_request); if (req == NULL) { map_oom(ac->module); return NULL; } req->operation = LDB_SEARCH; req->op.search.base = dn; req->op.search.scope = LDB_SCOPE_BASE; req->op.search.attrs = attrs; if (tree) { req->op.search.tree = tree; } else { req->op.search.tree = ldb_parse_tree(req, NULL); if (req->op.search.tree == NULL) { talloc_free(req); return NULL; } } req->controls = NULL; req->context = context; req->callback = callback; ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, req); return req;}/* Build a request to search the local record by its DN. */struct ldb_request *map_search_self_req(struct map_context *ac, struct ldb_dn *dn){ /* attrs[] is returned from this function in * ac->search_req->op.search.attrs, so it must be static, as * otherwise the compiler can put it on the stack */ static const char * const attrs[] = { IS_MAPPED, NULL }; struct ldb_parse_tree *tree; /* Limit search to records with 'IS_MAPPED' present */ /* TODO: `tree = ldb_parse_tree(ac, IS_MAPPED);' won't do. */ tree = talloc_zero(ac, struct ldb_parse_tree); if (tree == NULL) { map_oom(ac->module); return NULL; } tree->operation = LDB_OP_PRESENT; tree->u.present.attr = talloc_strdup(tree, IS_MAPPED); return map_search_base_req(ac, dn, attrs, tree, ac, map_search_self_callback);}/* Build a request to update the 'IS_MAPPED' attribute */struct ldb_request *map_build_fixup_req(struct map_context *ac, struct ldb_dn *olddn, struct ldb_dn *newdn){ struct ldb_request *req; struct ldb_message *msg; const char *dn; /* Prepare request */ req = talloc_zero(ac, struct ldb_request); if (req == NULL) { map_oom(ac->module); return NULL; } /* Prepare message */ msg = ldb_msg_new(req); if (msg == NULL) { map_oom(ac->module); goto failed; } /* Update local 'IS_MAPPED' to the new remote DN */ msg->dn = ldb_dn_copy(msg, olddn); dn = ldb_dn_alloc_linearized(msg, newdn); if ( ! dn || ! ldb_dn_validate(msg->dn)) { goto failed; } if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { goto failed; } if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { goto failed; } req->operation = LDB_MODIFY; req->op.mod.message = msg; req->controls = NULL; req->handle = NULL; req->context = NULL; req->callback = NULL; return req;failed: talloc_free(req); return NULL;}/* Asynchronous call structure * =========================== *//* Figure out which request is currently pending. */static struct ldb_request *map_get_req(struct map_context *ac){ switch (ac->step) { case MAP_SEARCH_SELF_MODIFY: case MAP_SEARCH_SELF_DELETE: case MAP_SEARCH_SELF_RENAME: return ac->search_req; case MAP_ADD_REMOTE: case MAP_MODIFY_REMOTE: case MAP_DELETE_REMOTE: case MAP_RENAME_REMOTE: return ac->remote_req; case MAP_RENAME_FIXUP: return ac->down_req; case MAP_ADD_LOCAL: case MAP_MODIFY_LOCAL: case MAP_DELETE_LOCAL: case MAP_RENAME_LOCAL: return ac->local_req; case MAP_SEARCH_REMOTE: /* Can't happen */ break; } return NULL; /* unreachable; silences a warning */}typedef int (*map_next_function)(struct ldb_handle *handle);/* Figure out the next request to run. */static map_next_function map_get_next(struct map_context *ac){ switch (ac->step) { case MAP_SEARCH_REMOTE: return NULL; case MAP_ADD_LOCAL: return map_add_do_remote; case MAP_ADD_REMOTE: return NULL; case MAP_SEARCH_SELF_MODIFY: return map_modify_do_local; case MAP_MODIFY_LOCAL: return map_modify_do_remote; case MAP_MODIFY_REMOTE: return NULL; case MAP_SEARCH_SELF_DELETE: return map_delete_do_local; case MAP_DELETE_LOCAL: return map_delete_do_remote; case MAP_DELETE_REMOTE: return NULL; case MAP_SEARCH_SELF_RENAME: return map_rename_do_local; case MAP_RENAME_LOCAL: return map_rename_do_fixup; case MAP_RENAME_FIXUP: return map_rename_do_remote; case MAP_RENAME_REMOTE: return NULL; } return NULL; /* unreachable; silences a warning */}/* Wait for the current pending request to finish and continue with the next. */static int map_wait_next(struct ldb_handle *handle){ struct map_context *ac; struct ldb_request *req; map_next_function next; int ret; if (handle == NULL || handle->private_data == NULL) { return LDB_ERR_OPERATIONS_ERROR; } if (handle->state == LDB_ASYNC_DONE) { return handle->status; } handle->state = LDB_ASYNC_PENDING; handle->status = LDB_SUCCESS; ac = talloc_get_type(handle->private_data, struct map_context); if (ac->step == MAP_SEARCH_REMOTE) { int i; for (i = 0; i < ac->num_searches; i++) { req = ac->search_reqs[i]; ret = ldb_wait(req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } if (req->handle->status != LDB_SUCCESS) { handle->status = req->handle->status; goto done; } if (req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } } else { req = map_get_req(ac); ret = ldb_wait(req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } if (req->handle->status != LDB_SUCCESS) { handle->status = req->handle->status; goto done; } if (req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } next = map_get_next(ac); if (next) { return next(handle); } } ret = LDB_SUCCESS;done: handle->state = LDB_ASYNC_DONE; return ret;}/* Wait for all current pending requests to finish. */static int map_wait_all(struct ldb_handle *handle){ int ret; while (handle->state != LDB_ASYNC_DONE) { ret = map_wait_next(handle); if (ret != LDB_SUCCESS) { return ret; } } return handle->status;}/* Wait for pending requests to finish. */int map_wait(struct ldb_handle *handle, enum ldb_wait_type type){ if (type == LDB_WAIT_ALL) { return map_wait_all(handle); } else { return map_wait_next(handle); }}/* Module initialization * ===================== *//* Builtin mappings for DNs and objectClasses */static const struct ldb_map_attribute builtin_attribute_maps[] = { { .local_name = "dn", .type = MAP_CONVERT, .u = { .convert = { .remote_name = "dn", .convert_local = ldb_dn_convert_local, .convert_remote = ldb_dn_convert_remote, }, }, }, { .local_name = NULL, }};static const struct ldb_map_attribute objectclass_attribute_map = { .local_name = "objectClass", .type = MAP_GENERATE, .convert_operator = map_objectclass_convert_operator, .u = { .generate = { .remote_names = { "objectClass", NULL }, .generate_local = map_objectclass_generate_local, .generate_remote = map_objectclass_generate_remote, }, },};/* Find the special 'MAP_DN_NAME' record and store local and remote * base DNs in private data. */static int map_init_dns(struct ldb_module *module, struct ldb_map_context *data, const char *name){ static const char * const attrs[] = { MAP_DN_FROM, MAP_DN_TO, NULL }; struct ldb_dn *dn; struct ldb_message *msg; struct ldb_result *res; int ret; if (!name) { data->local_base_dn = NULL; data->remote_base_dn = NULL; return LDB_SUCCESS; } dn = ldb_dn_new_fmt(data, module->ldb, "%s=%s", MAP_DN_NAME, name); if ( ! ldb_dn_validate(dn)) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "Failed to construct '%s' DN!\n", MAP_DN_NAME); return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_search(module->ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res); talloc_free(dn); if (ret != LDB_SUCCESS) { return ret; } if (res->count == 0) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "No results for '%s=%s'!\n", MAP_DN_NAME, name); talloc_free(res); return LDB_ERR_CONSTRAINT_VIOLATION; } if (res->count > 1) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "Too many results for '%s=%s'!\n", MAP_DN_NAME, name); talloc_free(res); return LDB_ERR_CONSTRAINT_VIOLATION; } msg = res->msgs[0]; data->local_base_dn = ldb_msg_find_attr_as_dn(module->ldb, data, msg, MAP_DN_FROM); data->remote_base_dn = ldb_msg_find_attr_as_dn(module->ldb, data, msg, MAP_DN_TO); talloc_free(res); return LDB_SUCCESS;}/* Store attribute maps and objectClass maps in private data. */static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char * const *wildcard_attributes){ int i, j, last; last = 0; /* Count specified attribute maps */ for (i = 0; attrs[i].local_name; i++) /* noop */ ; /* Count built-in attribute maps */ for (j = 0; builtin_attribute_maps[j].local_name; j++) /* noop */ ; /* Store list of attribute maps */ data->attribute_maps = talloc_array(data, struct ldb_map_attribute, i+j+2); if (data->attribute_maps == NULL) { map_oom(module); return LDB_ERR_OPERATIONS_ERROR; } /* Specified ones go first */ for (i = 0; attrs[i].local_name; i++) { data->attribute_maps[last] = attrs[i]; last++; } /* Built-in ones go last */ for (i = 0; builtin_attribute_maps[i].local_name; i++) { data->attribute_maps[last] = builtin_attribute_maps[i]; last++; } if (data->add_objectclass) { /* ObjectClass one is very last, if required */ data->attribute_maps[last] = objectclass_attribute_map; last++; } else if (ocls) { data->attribute_maps[last] = objectclass_convert_map; last++; } /* Ensure 'local_name == NULL' for the last entry */ memset(&data->attribute_maps[last], 0, sizeof(struct ldb_map_attribute)); /* Store list of objectClass maps */ data->objectclass_maps = ocls; data->wildcard_attributes = wildcard_attributes; return LDB_SUCCESS;}/* Initialize global private data. */_PUBLIC_ int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, const struct ldb_map_objectclass *ocls, const char * const *wildcard_attributes, const char *add_objectclass, const char *name){ struct map_private *data; int ret; /* Prepare private data */ data = talloc_zero(module, struct map_private); if (data == NULL) { map_oom(module); return LDB_ERR_OPERATIONS_ERROR; } module->private_data = data; data->context = talloc_zero(data, struct ldb_map_context); if (!data->context) { map_oom(module); return LDB_ERR_OPERATIONS_ERROR; } /* Store local and remote baseDNs */ ret = map_init_dns(module, data->context, name); if (ret != LDB_SUCCESS) { talloc_free(data); return ret; } data->context->add_objectclass = add_objectclass; /* Store list of attribute and objectClass maps */ ret = map_init_maps(module, data->context, attrs, ocls, wildcard_attributes); if (ret != LDB_SUCCESS) { talloc_free(data); return ret; } return LDB_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -