static int construct_msds_isrodc_with_dn(struct ldb_module *module, struct ldb_message *msg, struct ldb_message_element *object_category) { struct ldb_context *ldb; struct ldb_dn *dn; const struct ldb_val *val; ldb = ldb_module_get_ctx(module); if (!ldb) { DEBUG(4, (__location__ ": Failed to get ldb \n")); return ldb_operr(ldb); } dn = ldb_dn_new(msg, ldb, (const char *)object_category->values[0].data); if (!dn) { DEBUG(4, (__location__ ": Failed to create dn from %s \n", (const char *)object_category->values[0].data)); return ldb_operr(ldb); } val = ldb_dn_get_rdn_val(dn); if (!val) { DEBUG(4, (__location__ ": Failed to get rdn val from %s \n", ldb_dn_get_linearized(dn))); return ldb_operr(ldb); } if (strequal((const char *)val->data, "NTDS-DSA")) { ldb_msg_add_string(msg, "msDS-isRODC", "FALSE"); } else { ldb_msg_add_string(msg, "msDS-isRODC", "TRUE"); } return LDB_SUCCESS; }
} END_TEST // ^ Unit test ---------------------------------------------------------------- // v Suite definition --------------------------------------------------------- static void create_ldb_from_ldif(const char *ldb_path, const char *ldif_path, const char *default_context, const char *root_context) { FILE *f; struct ldb_ldif *ldif; struct ldb_context *ldb_ctx = NULL; TALLOC_CTX *local_mem_ctx = talloc_new(NULL); struct ldb_message *msg; ldb_ctx = ldb_init(local_mem_ctx, NULL); ldb_connect(ldb_ctx, ldb_path, 0, 0); f = fopen(ldif_path, "r"); msg = ldb_msg_new(local_mem_ctx); msg->dn = ldb_dn_new(msg, ldb_ctx, "@INDEXLIST"); ldb_msg_add_string(msg, "@IDXATTR", "cn"); ldb_msg_add_string(msg, "@IDXATTR", "oleguid"); ldb_msg_add_string(msg, "@IDXATTR", "mappedId"); msg->elements[0].flags = LDB_FLAG_MOD_ADD; ldb_add(ldb_ctx, msg); while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) { struct ldb_message *normalized_msg; ldb_msg_normalize(ldb_ctx, local_mem_ctx, ldif->msg, &normalized_msg); ldb_add(ldb_ctx, normalized_msg); talloc_free(normalized_msg); ldb_ldif_read_free(ldb_ctx, ldif); } if (default_context && root_context) { msg = ldb_msg_new(local_mem_ctx); msg->dn = ldb_dn_new(msg, ldb_ctx, "@ROOTDSE"); ldb_msg_add_string(msg, "defaultNamingContext", default_context); ldb_msg_add_string(msg, "rootDomainNamingContext", root_context); msg->elements[0].flags = LDB_FLAG_MOD_REPLACE; ldb_add(ldb_ctx, msg); } fclose(f); talloc_free(local_mem_ctx); }
static int construct_modifyTimeStamp(struct ldb_module *module, struct ldb_message *msg, enum ldb_scope scope, struct ldb_request *parent) { struct operational_data *data = talloc_get_type(ldb_module_get_private(module), struct operational_data); struct ldb_context *ldb = ldb_module_get_ctx(module); /* We may be being called before the init function has finished */ if (!data) { return LDB_SUCCESS; } /* Try and set this value up, if possible. Don't worry if it * fails, we may not have the DB set up yet. */ if (!data->aggregate_dn) { data->aggregate_dn = samdb_aggregate_schema_dn(ldb, data); } if (data->aggregate_dn && ldb_dn_compare(data->aggregate_dn, msg->dn) == 0) { /* * If we have the DN for the object with common name = Aggregate and * the request is for this DN then let's do the following: * 1) search the object which changedUSN correspond to the one of the loaded * schema. * 2) Get the whenChanged attribute * 3) Generate the modifyTimestamp out of the whenChanged attribute */ const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL); char *value = ldb_timestring(msg, schema->ts_last_change); return ldb_msg_add_string(msg, "modifyTimeStamp", value); } return ldb_msg_copy_attr(msg, "whenChanged", "modifyTimeStamp"); }
/* add a new record */ static isc_result_t b9_add_record(struct dlz_bind9_data *state, const char *name, struct ldb_dn *dn, struct dnsp_DnssrvRpcRecord *rec) { struct ldb_message *msg; enum ndr_err_code ndr_err; struct ldb_val v; int ret; msg = ldb_msg_new(rec); if (msg == NULL) { return ISC_R_NOMEMORY; } msg->dn = dn; ret = ldb_msg_add_string(msg, "objectClass", "dnsNode"); if (ret != LDB_SUCCESS) { return ISC_R_FAILURE; } ndr_err = ndr_push_struct_blob(&v, rec, rec, (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ISC_R_FAILURE; } ret = ldb_msg_add_value(msg, "dnsRecord", &v, NULL); if (ret != LDB_SUCCESS) { return ISC_R_FAILURE; } ret = ldb_add(state->samdb, msg); if (ret != LDB_SUCCESS) { return ISC_R_FAILURE; } return ISC_R_SUCCESS; }
/* Modify the local record. */ int map_modify_do_local(struct ldb_handle *handle) { struct map_context *ac; struct ldb_message *msg; char *dn; ac = talloc_get_type(handle->private_data, struct map_context); if (ac->local_dn == NULL) { /* No local record present, add it instead */ msg = discard_const_p(struct ldb_message, ac->local_req->op.mod.message); /* Add local 'IS_MAPPED' */ /* TODO: use GUIDs here instead */ dn = ldb_dn_linearize(msg, ac->remote_req->op.mod.message->dn); if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_ADD, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { return LDB_ERR_OPERATIONS_ERROR; } /* Turn request into 'add' */ ac->local_req->operation = LDB_ADD; ac->local_req->op.add.message = msg; /* TODO: Could I just leave msg in there? I think so, * but it looks clearer this way. */ }
/* add a group mapping entry */ static bool add_mapping_entry(GROUP_MAP *map, int flag) { struct ldb_message *msg; int ret, i; fstring string_sid; msg = ldb_msg_new(ldb); if (msg == NULL) { return False; } msg->dn = mapping_dn(msg, &map->sid); if (msg->dn == NULL) { goto failed; } if (ldb_msg_add_string(msg, "objectClass", "groupMap") != LDB_SUCCESS || ldb_msg_add_string(msg, "sid", sid_to_fstring(string_sid, &map->sid)) != LDB_SUCCESS || ldb_msg_add_fmt(msg, "gidNumber", "%u", (unsigned)map->gid) != LDB_SUCCESS || ldb_msg_add_fmt(msg, "sidNameUse", "%u", (unsigned)map->sid_name_use) != LDB_SUCCESS || ldb_msg_add_string(msg, "comment", map->comment) != LDB_SUCCESS || ldb_msg_add_string(msg, "ntName", map->nt_name) != LDB_SUCCESS) { goto failed; } ret = ldb_add(ldb, msg); /* if it exists we update it. This is a hangover from the semantics the tdb backend had */ if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { for (i=0;i<msg->num_elements;i++) { msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; } ret = ldb_modify(ldb, msg); } talloc_free(msg); return ret == LDB_SUCCESS; failed: talloc_free(msg); return False; }
static int acl_childClasses(struct ldb_module *module, struct ldb_message *sd_msg, struct ldb_message *msg, const char *attrName) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; int i, j, ret; /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { return LDB_SUCCESS; } /* Must remove any existing attribute, or else confusion reins */ ldb_msg_remove_attr(msg, attrName); ret = ldb_msg_add_empty(msg, attrName, 0, &allowedClasses); if (ret != LDB_SUCCESS) { return ret; } oc_el = ldb_msg_find_element(sd_msg, "objectClass"); for (i=0; oc_el && i < oc_el->num_values; i++) { sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { /* We don't know this class? what is going on? */ continue; } for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { ldb_msg_add_string(msg, attrName, sclass->possibleInferiors[j]); } } if (allowedClasses->num_values > 1) { qsort(allowedClasses->values, allowedClasses->num_values, sizeof(*allowedClasses->values), (comparison_fn_t)data_blob_cmp); for (i=1 ; i < allowedClasses->num_values; i++) { struct ldb_val *val1 = &allowedClasses->values[i-1]; struct ldb_val *val2 = &allowedClasses->values[i]; if (data_blob_cmp(val1, val2) == 0) { memmove(val1, val2, (allowedClasses->num_values - i) * sizeof(struct ldb_val)); allowedClasses->num_values--; i--; } } } return LDB_SUCCESS; }
static int hybrid_domain_user_to_group(struct cache_req_result *result) { errno_t ret; uid_t uid; gid_t gid; /* There must be exactly one entry.. */ if (result == NULL || result->count != 1) { DEBUG(SSSDBG_CRIT_FAILURE, "No result or wrong number of entries, expected 1 entry\n"); return ENOENT; } /* ...which has uidNumber equal to gidNumber */ uid = sss_view_ldb_msg_find_attr_as_uint64(result->domain, result->msgs[0], SYSDB_UIDNUM, 0); gid = sss_view_ldb_msg_find_attr_as_uint64(result->domain, result->msgs[0], SYSDB_GIDNUM, 0); if (uid == 0 || uid != gid) { DEBUG(SSSDBG_TRACE_INTERNAL, "UID and GID differ\n"); return ENOENT; } /* OK, we have a user with uid == gid; let's pretend this is a group */ ret = ldb_msg_add_string(result->msgs[0], SYSDB_OBJECTCATEGORY, SYSDB_GROUP_CLASS); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add group class\n"); return ret; } return EOK; }
/* * Test the a modify with no object SID is passed through correctly * */ static void test_modify_no_objectSID(void **state) { struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx); struct ldb_context *ldb = test_ctx->ldb; struct ldb_message *msg = ldb_msg_new(test_ctx); struct ldb_request *request = NULL; struct ldb_request *original_request = NULL; int rc; msg->dn = ldb_dn_new(msg, ldb, "dc=test"); assert_int_equal(LDB_SUCCESS, ldb_msg_add_string(msg, "cn", "test")); rc = ldb_build_mod_req( &request, test_ctx->ldb, test_ctx, msg, NULL, NULL, ldb_op_default_callback, NULL); assert_int_equal(rc, LDB_SUCCESS); assert_non_null(request); original_request = request; rc = unique_object_sids_modify(test_ctx->module, request); assert_int_equal(rc, LDB_SUCCESS); /* * Check that the original request was passed to the next module * and not a copy */ assert_ptr_equal(last_request, original_request); }
/* Add a record. */ int map_add(struct ldb_module *module, struct ldb_request *req) { const struct ldb_message *msg = req->op.add.message; struct ldb_handle *h; struct map_context *ac; struct ldb_message *local, *remote; const char *dn; /* Do not manipulate our control entries */ if (ldb_dn_is_special(msg->dn)) { return ldb_next_request(module, req); } /* No mapping requested (perhaps no DN mapping specified), skip to next module */ if (!ldb_dn_check_local(module, msg->dn)) { return ldb_next_request(module, req); } /* No mapping needed, fail */ if (!ldb_msg_check_remote(module, msg)) { return LDB_ERR_OPERATIONS_ERROR; } /* Prepare context and handle */ h = map_init_handle(req, module); if (h == NULL) { return LDB_ERR_OPERATIONS_ERROR; } ac = talloc_get_type(h->private_data, struct map_context); /* Prepare the local operation */ ac->local_req = talloc(ac, struct ldb_request); if (ac->local_req == NULL) { goto oom; } *(ac->local_req) = *req; /* copy the request */ ac->local_req->context = NULL; ac->local_req->callback = NULL; /* Prepare the remote operation */ ac->remote_req = talloc(ac, struct ldb_request); if (ac->remote_req == NULL) { goto oom; } *(ac->remote_req) = *req; /* copy the request */ ac->remote_req->context = NULL; ac->remote_req->callback = NULL; /* Prepare the local message */ local = ldb_msg_new(ac->local_req); if (local == NULL) { goto oom; } local->dn = msg->dn; /* Prepare the remote message */ remote = ldb_msg_new(ac->remote_req); if (remote == NULL) { goto oom; } remote->dn = ldb_dn_map_local(ac->module, remote, msg->dn); /* Split local from remote message */ ldb_msg_partition(module, local, remote, msg); ac->local_req->op.add.message = local; ac->remote_req->op.add.message = remote; if ((local->num_elements == 0) || (!map_check_local_db(ac->module))) { /* No local data or db, just run the remote request */ talloc_free(ac->local_req); req->handle = h; /* return our own handle to deal with this call */ return map_add_do_remote(h); } /* Store remote DN in 'IS_MAPPED' */ /* TODO: use GUIDs here instead */ dn = ldb_dn_linearize(local, remote->dn); if (ldb_msg_add_string(local, IS_MAPPED, dn) != 0) { goto failed; } req->handle = h; /* return our own handle to deal with this call */ return map_add_do_local(h); oom: map_oom(module); failed: talloc_free(h); return LDB_ERR_OPERATIONS_ERROR; }
int sysdb_upgrade_10(struct sysdb_ctx *sysdb, const char **ver) { TALLOC_CTX *tmp_ctx; int ret; struct ldb_result *res; struct ldb_message *msg; struct ldb_message *user; struct ldb_message_element *memberof_el; const char *name; struct ldb_dn *basedn; const char *filter = "(&(objectClass=user)(!(uidNumber=*))(memberOf=*))"; const char *attrs[] = { "name", "memberof", NULL }; int i, j; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_USER_BASE, sysdb->domain->name); if (basedn == NULL) { ret = EIO; goto done; } DEBUG(SSSDBG_CRIT_FAILURE, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_11)); ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } ret = ldb_search(sysdb->ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE, attrs, "%s", filter); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } for (i = 0; i < res->count; i++) { user = res->msgs[i]; memberof_el = ldb_msg_find_element(user, "memberof"); name = ldb_msg_find_attr_as_string(user, "name", NULL); if (name == NULL) { ret = EIO; goto done; } for (j = 0; j < memberof_el->num_values; j++) { msg = ldb_msg_new(tmp_ctx); if (msg == NULL) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_from_ldb_val(tmp_ctx, sysdb->ldb, &memberof_el->values[j]); if (msg->dn == NULL) { ret = ENOMEM; goto done; } if (!ldb_dn_validate(msg->dn)) { DEBUG(SSSDBG_MINOR_FAILURE, ("DN validation failed during " "upgrade: [%s]\n", memberof_el->values[j].data)); talloc_zfree(msg); continue; } ret = ldb_msg_add_empty(msg, "ghost", LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "ghost", name); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "member", LDB_FLAG_MOD_DELETE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "member", ldb_dn_get_linearized(user->dn)); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); talloc_zfree(msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } ret = ldb_delete(sysdb->ldb, user->dn); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_11); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_11, ver); talloc_free(tmp_ctx); return ret; }
static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes) { int ret = LDB_SUCCESS; struct ldb_result *res; struct ldb_result *res_idx; struct dsdb_attribute *attr; struct ldb_message *mod_msg; TALLOC_CTX *mem_ctx; struct ldb_message *msg; struct ldb_message *msg_idx; /* setup our own attribute name to schema handler */ ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema); if (!write_attributes) { return ret; } mem_ctx = talloc_new(ldb); if (!mem_ctx) { return ldb_oom(ldb); } msg = ldb_msg_new(mem_ctx); if (!msg) { ldb_oom(ldb); goto op_error; } msg_idx = ldb_msg_new(mem_ctx); if (!msg_idx) { ldb_oom(ldb); goto op_error; } msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES"); if (!msg->dn) { ldb_oom(ldb); goto op_error; } msg_idx->dn = ldb_dn_new(msg_idx, ldb, "@INDEXLIST"); if (!msg_idx->dn) { ldb_oom(ldb); goto op_error; } ret = ldb_msg_add_string(msg_idx, "@IDXONE", "1"); if (ret != LDB_SUCCESS) { goto op_error; } ret = ldb_msg_add_string(msg_idx, "@IDXVERSION", SAMDB_INDEXING_VERSION); if (ret != LDB_SUCCESS) { goto op_error; } for (attr = schema->attributes; attr; attr = attr->next) { const char *syntax = attr->syntax->ldb_syntax; if (!syntax) { syntax = attr->syntax->ldap_oid; } /* * Write out a rough approximation of the schema * as an @ATTRIBUTES value, for bootstrapping */ if (strcmp(syntax, LDB_SYNTAX_INTEGER) == 0) { ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "INTEGER"); } else if (strcmp(syntax, LDB_SYNTAX_DIRECTORY_STRING) == 0) { ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE"); } if (ret != LDB_SUCCESS) { break; } if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) { ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName); if (ret != LDB_SUCCESS) { break; } } } if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; } /* * Try to avoid churning the attributes too much, * we only want to do this if they have changed */ ret = ldb_search(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, NULL); if (ret == LDB_ERR_NO_SUCH_OBJECT) { ret = ldb_add(ldb, msg); } else if (ret != LDB_SUCCESS) { } else if (res->count != 1) { ret = ldb_add(ldb, msg); } else { ret = LDB_SUCCESS; /* Annoyingly added to our search results */ ldb_msg_remove_attr(res->msgs[0], "distinguishedName"); ret = ldb_msg_difference(ldb, mem_ctx, res->msgs[0], msg, &mod_msg); if (ret != LDB_SUCCESS) { goto op_error; } if (mod_msg->num_elements > 0) { ret = dsdb_replace(ldb, mod_msg, 0); } talloc_free(mod_msg); } if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS || ret == LDB_ERR_INVALID_DN_SYNTAX) { /* We might be on a read-only DB or LDAP */ ret = LDB_SUCCESS; } if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; } /* Now write out the indexes, as found in the schema (if they have changed) */ ret = ldb_search(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE, NULL, NULL); if (ret == LDB_ERR_NO_SUCH_OBJECT) { ret = ldb_add(ldb, msg_idx); } else if (ret != LDB_SUCCESS) { } else if (res_idx->count != 1) { ret = ldb_add(ldb, msg_idx); } else { ret = LDB_SUCCESS; /* Annoyingly added to our search results */ ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName"); ret = ldb_msg_difference(ldb, mem_ctx, res_idx->msgs[0], msg_idx, &mod_msg); if (ret != LDB_SUCCESS) { goto op_error; } if (mod_msg->num_elements > 0) { ret = dsdb_replace(ldb, mod_msg, 0); } talloc_free(mod_msg); } if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS || ret == LDB_ERR_INVALID_DN_SYNTAX) { /* We might be on a read-only DB */ ret = LDB_SUCCESS; } talloc_free(mem_ctx); return ret; op_error: talloc_free(mem_ctx); return ldb_operr(ldb); }
/* * find out Site specific stuff: * 1. Lookup the Site name. * 2. Add entry CN=<netbios name>,CN=Servers,CN=<site name>,CN=Sites,CN=Configuration,<domain dn>. * TODO: 3.) use DsAddEntry() to create CN=NTDS Settings,CN=<netbios name>,CN=Servers,CN=<site name>,... */ NTSTATUS libnet_JoinSite(struct libnet_context *ctx, struct ldb_context *remote_ldb, struct libnet_JoinDomain *libnet_r) { NTSTATUS status; TALLOC_CTX *tmp_ctx; struct libnet_JoinSite *r; struct ldb_dn *server_dn; struct ldb_message *msg; int rtn; const char *server_dn_str; const char *config_dn_str; struct nbt_name name; const char *dest_addr = NULL; tmp_ctx = talloc_named(libnet_r, 0, "libnet_JoinSite temp context"); if (!tmp_ctx) { libnet_r->out.error_string = NULL; return NT_STATUS_NO_MEMORY; } r = talloc(tmp_ctx, struct libnet_JoinSite); if (!r) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } make_nbt_name_client(&name, libnet_r->out.samr_binding->host); status = resolve_name(lp_resolve_context(ctx->lp_ctx), &name, r, &dest_addr, ctx->event_ctx); if (!NT_STATUS_IS_OK(status)) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return status; } /* Resolve the site name and AD DN's. */ r->in.dest_address = dest_addr; r->in.netbios_name = libnet_r->in.netbios_name; r->in.domain_dn_str = libnet_r->out.domain_dn_str; r->in.cldap_port = lp_cldap_port(ctx->lp_ctx); status = libnet_FindSite(tmp_ctx, ctx, r); if (!NT_STATUS_IS_OK(status)) { libnet_r->out.error_string = talloc_steal(libnet_r, r->out.error_string); talloc_free(tmp_ctx); return status; } config_dn_str = r->out.config_dn_str; server_dn_str = r->out.server_dn_str; /* Add entry CN=<netbios name>,CN=Servers,CN=<site name>,CN=Sites,CN=Configuration,<domain dn>. */ msg = ldb_msg_new(tmp_ctx); if (!msg) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = ldb_msg_add_string(msg, "objectClass", "server"); if (rtn != 0) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = ldb_msg_add_string(msg, "systemFlags", "50000000"); if (rtn != 0) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = ldb_msg_add_string(msg, "serverReference", libnet_r->out.account_dn_str); if (rtn != 0) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } server_dn = ldb_dn_new(tmp_ctx, remote_ldb, server_dn_str); if ( ! ldb_dn_validate(server_dn)) { libnet_r->out.error_string = talloc_asprintf(libnet_r, "Invalid server dn: %s", server_dn_str); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } msg->dn = server_dn; rtn = ldb_add(remote_ldb, msg); if (rtn == LDB_ERR_ENTRY_ALREADY_EXISTS) { int i; /* make a 'modify' msg, and only for serverReference */ msg = ldb_msg_new(tmp_ctx); if (!msg) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } msg->dn = server_dn; rtn = ldb_msg_add_string(msg, "serverReference",libnet_r->out.account_dn_str); if (rtn != 0) { libnet_r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } /* mark all the message elements (should be just one) as LDB_FLAG_MOD_REPLACE */ for (i=0; i<msg->num_elements; i++) { msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; } rtn = ldb_modify(remote_ldb, msg); if (rtn != 0) { libnet_r->out.error_string = talloc_asprintf(libnet_r, "Failed to modify server entry %s: %s: %d", server_dn_str, ldb_errstring(remote_ldb), rtn); talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } } else if (rtn != 0) { libnet_r->out.error_string = talloc_asprintf(libnet_r, "Failed to add server entry %s: %s: %d", server_dn_str, ldb_errstring(remote_ldb), rtn); talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } DEBUG(0, ("We still need to perform a DsAddEntry() so that we can create the CN=NTDS Settings container.\n")); /* Store the server DN in libnet_r */ libnet_r->out.server_dn_str = server_dn_str; talloc_steal(libnet_r, server_dn_str); talloc_free(tmp_ctx); return NT_STATUS_OK; }
int sysdb_upgrade_08(struct sysdb_ctx *sysdb, const char **ver) { TALLOC_CTX *tmp_ctx; int ret; struct ldb_message *msg; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_9)); ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } /* Add new indexes */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); if (!msg->dn) { ret = ENOMEM; goto done; } /* Add Index for servicePort and serviceProtocol */ ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "@IDXATTR", "servicePort"); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "@IDXATTR", "serviceProtocol"); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_9); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_9, ver); talloc_free(tmp_ctx); return ret; }
errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, const char *flat, const char *id, const char* forest) { TALLOC_CTX *tmp_ctx; struct ldb_message *msg; int ret; bool do_update = false; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } msg = ldb_msg_new(tmp_ctx); if (msg == NULL) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_DOM_BASE, domain->name); if (msg->dn == NULL) { ret = EIO; goto done; } if (flat != NULL && (domain->flat_name == NULL || strcmp(domain->flat_name, flat) != 0)) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT, LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } do_update = true; } if (id != NULL && (domain->domain_id == NULL || strcmp(domain->domain_id, id) != 0)) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID, LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, id); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } do_update = true; } if (forest != NULL && (domain->forest == NULL || strcmp(domain->forest, forest) != 0)) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } do_update = true; } if (do_update == false) { ret = EOK; goto done; } ret = ldb_modify(domain->sysdb->ldb, msg); if (ret != LDB_SUCCESS) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to " "[%s]: [%d][%s]!\n", domain->name, ret, ldb_errstring(domain->sysdb->ldb)); ret = sysdb_error_to_errno(ret); goto done; } ret = sysdb_master_domain_update(domain); if (ret != EOK) { goto done; } ret = EOK; done: talloc_free(tmp_ctx); return ret; }
/* serach all groups that have a memberUid attribute. * change it into a member attribute for a user of same domain. * remove the memberUid attribute * add the new member attribute * finally stop indexing memberUid * upgrade version to 0.2 */ int sysdb_upgrade_01(struct ldb_context *ldb, const char **ver) { struct ldb_message_element *el; struct ldb_result *res; struct ldb_dn *basedn; struct ldb_dn *mem_dn; struct ldb_message *msg; const struct ldb_val *val; const char *filter = "(&(memberUid=*)(objectclass=group))"; const char *attrs[] = { "memberUid", NULL }; const char *mdn; char *domain; int ret, i, j; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { ret = ENOMEM; goto done; } basedn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); if (!basedn) { ret = EIO; goto done; } ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE, attrs, "%s", filter); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } ret = ldb_transaction_start(ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } for (i = 0; i < res->count; i++) { el = ldb_msg_find_element(res->msgs[i], "memberUid"); if (!el) { DEBUG(1, ("memberUid is missing from message [%s], skipping\n", ldb_dn_get_linearized(res->msgs[i]->dn))); continue; } /* create modification message */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = res->msgs[i]->dn; ret = ldb_msg_add_empty(msg, "memberUid", LDB_FLAG_MOD_DELETE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } /* get domain name component value */ val = ldb_dn_get_component_val(res->msgs[i]->dn, 2); domain = talloc_strndup(tmp_ctx, (const char *)val->data, val->length); if (!domain) { ret = ENOMEM; goto done; } for (j = 0; j < el->num_values; j++) { mem_dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_USER, (const char *)el->values[j].data, domain); if (!mem_dn) { ret = ENOMEM; goto done; } mdn = talloc_strdup(msg, ldb_dn_get_linearized(mem_dn)); if (!mdn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, SYSDB_MEMBER, mdn); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } talloc_zfree(mem_dn); } /* ok now we are ready to modify the entry */ ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } talloc_zfree(msg); } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, ldb, SYSDB_VERSION_0_2, ver); talloc_free(tmp_ctx); return ret; }
int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver) { TALLOC_CTX *tmp_ctx; int ret; struct ldb_message *msg; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_7)); ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } /* Add new indexes */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); if (!msg->dn) { ret = ENOMEM; goto done; } /* Case insensitive search for originalDN */ ret = ldb_msg_add_empty(msg, SYSDB_ORIG_DN, LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, SYSDB_ORIG_DN, "CASE_INSENSITIVE"); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "cn=sysdb"); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_7); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_7, ver); talloc_free(tmp_ctx); return ret; }
errno_t sysdb_svc_add(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *primary_name, int port, const char **aliases, const char **protocols, struct ldb_dn **dn) { errno_t ret; int lret; TALLOC_CTX *tmp_ctx; struct ldb_message *msg; unsigned long i; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } /* svc dn */ msg->dn = sysdb_svc_dn(domain->sysdb, msg, domain->name, primary_name); if (!msg->dn) { ret = ENOMEM; goto done; } /* Objectclass */ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_SVC_CLASS); if (ret != EOK) goto done; /* Set the primary name */ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, primary_name); if (ret != EOK) goto done; /* Set the port number */ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_SVC_PORT, port); if (ret != EOK) goto done; /* If this service has any aliases, include them */ if (aliases && aliases[0]) { /* Set the name aliases */ lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, LDB_FLAG_MOD_ADD, NULL); if (lret != LDB_SUCCESS) { ret = sysdb_error_to_errno(lret); goto done; } for (i=0; aliases[i]; i++) { lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]); if (lret != LDB_SUCCESS) { ret = sysdb_error_to_errno(lret); goto done; } } } /* Set the protocols */ lret = ldb_msg_add_empty(msg, SYSDB_SVC_PROTO, LDB_FLAG_MOD_ADD, NULL); if (lret != LDB_SUCCESS) { ret = sysdb_error_to_errno(lret); goto done; } for (i=0; protocols[i]; i++) { lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]); if (lret != LDB_SUCCESS) { ret = sysdb_error_to_errno(lret); goto done; } } /* creation time */ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, (unsigned long)time(NULL)); if (ret) goto done; lret = ldb_add(domain->sysdb->ldb, msg); ret = sysdb_error_to_errno(lret); if (ret == EOK && dn) { *dn = talloc_steal(mem_ctx, msg->dn); } done: if (ret) { DEBUG(SSSDBG_TRACE_INTERNAL, "Error: %d (%s)\n", ret, strerror(ret)); } talloc_free(tmp_ctx); return ret; }
errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, const char *name, const char *realm, const char *flat_name, const char *domain_id, bool mpg, bool enumerate, const char *forest) { TALLOC_CTX *tmp_ctx; struct ldb_message *msg; struct ldb_dn *dn; struct ldb_result *res; const char *attrs[] = {"cn", SYSDB_SUBDOMAIN_REALM, SYSDB_SUBDOMAIN_FLAT, SYSDB_SUBDOMAIN_ID, SYSDB_SUBDOMAIN_MPG, SYSDB_SUBDOMAIN_ENUM, SYSDB_SUBDOMAIN_FOREST, NULL}; const char *tmp_str; bool tmp_bool; bool store = false; int realm_flags = 0; int flat_flags = 0; int id_flags = 0; int mpg_flags = 0; int enum_flags = 0; int forest_flags = 0; int ret; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, name); if (dn == NULL) { ret = EIO; goto done; } ret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } if (res->count == 0) { ret = sysdb_domain_create(sysdb, name); if (ret) { goto done; } store = true; if (realm) realm_flags = LDB_FLAG_MOD_ADD; if (flat_name) flat_flags = LDB_FLAG_MOD_ADD; if (domain_id) id_flags = LDB_FLAG_MOD_ADD; mpg_flags = LDB_FLAG_MOD_ADD; enum_flags = LDB_FLAG_MOD_ADD; if (forest) forest_flags = LDB_FLAG_MOD_ADD; } else if (res->count != 1) { ret = EINVAL; goto done; } else { /* 1 found */ if (realm) { tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_REALM, NULL); if (!tmp_str || strcasecmp(tmp_str, realm) != 0) { realm_flags = LDB_FLAG_MOD_REPLACE; } } if (flat_name) { tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FLAT, NULL); if (!tmp_str || strcasecmp(tmp_str, flat_name) != 0) { flat_flags = LDB_FLAG_MOD_REPLACE; } } if (domain_id) { tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_ID, NULL); if (!tmp_str || strcasecmp(tmp_str, domain_id) != 0) { id_flags = LDB_FLAG_MOD_REPLACE; } } tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_MPG, !mpg); if (tmp_bool != mpg) { mpg_flags = LDB_FLAG_MOD_REPLACE; } tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_ENUM, !enumerate); if (tmp_bool != enumerate) { enum_flags = LDB_FLAG_MOD_REPLACE; } if (forest) { tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FOREST, NULL); if (!tmp_str || strcasecmp(tmp_str, forest) != 0) { forest_flags = LDB_FLAG_MOD_REPLACE; } } } if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0 && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0) { ret = EOK; goto done; } msg = ldb_msg_new(tmp_ctx); if (msg == NULL) { ret = ENOMEM; goto done; } msg->dn = dn; if (store) { ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_SUBDOMAIN_CLASS); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (realm_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_REALM, realm_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (flat_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT, flat_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat_name); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (id_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID, id_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, domain_id); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (mpg_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_MPG, mpg_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_MPG, mpg ? "TRUE" : "FALSE"); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (enum_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ENUM, enum_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ENUM, enumerate ? "TRUE" : "FALSE"); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } if (forest_flags) { ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, forest_flags, NULL); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to " "[%s]: [%d][%s]!\n", name, ret, ldb_errstring(sysdb->ldb)); ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: talloc_free(tmp_ctx); return ret; }
/* remember an established session key for a netr server authentication use a simple ldb structure */ NTSTATUS schannel_store_session_key_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState *creds) { struct ldb_message *msg; struct ldb_val val, seed, client_state, server_state; struct ldb_val *sid_val; char *f; char *sct; int ret; f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); if (f == NULL) { return NT_STATUS_NO_MEMORY; } sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); if (sct == NULL) { return NT_STATUS_NO_MEMORY; } msg = ldb_msg_new(ldb); if (msg == NULL) { return NT_STATUS_NO_MEMORY; } msg->dn = ldb_dn_new_fmt(msg, ldb, "computerName=%s", creds->computer_name); if ( ! msg->dn) { return NT_STATUS_NO_MEMORY; } sid_val = schannel_dom_sid_ldb_val(msg, creds->sid); if (sid_val == NULL) { return NT_STATUS_NO_MEMORY; } val.data = creds->session_key; val.length = sizeof(creds->session_key); seed.data = creds->seed.data; seed.length = sizeof(creds->seed.data); client_state.data = creds->client.data; client_state.length = sizeof(creds->client.data); server_state.data = creds->server.data; server_state.length = sizeof(creds->server.data); ldb_msg_add_string(msg, "objectClass", "schannelState"); ldb_msg_add_value(msg, "sessionKey", &val, NULL); ldb_msg_add_value(msg, "seed", &seed, NULL); ldb_msg_add_value(msg, "clientState", &client_state, NULL); ldb_msg_add_value(msg, "serverState", &server_state, NULL); ldb_msg_add_string(msg, "negotiateFlags", f); ldb_msg_add_string(msg, "secureChannelType", sct); ldb_msg_add_string(msg, "accountName", creds->account_name); ldb_msg_add_string(msg, "computerName", creds->computer_name); ldb_msg_add_value(msg, "objectSid", sid_val, NULL); ret = ldb_add(ldb, msg); if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { int i; /* from samdb_replace() */ /* mark all the message elements as LDB_FLAG_MOD_REPLACE */ for (i=0;i<msg->num_elements;i++) { msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; } ret = ldb_modify(ldb, msg); } /* We don't need a transaction here, as we either add or * modify records, never delete them, so it must exist */ if (ret != LDB_SUCCESS) { DEBUG(0,("Unable to add %s to session key db - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } return NT_STATUS_OK; }
/** \details Set a list of properties on a message \param mem_ctx pointer to the memory context \param message_object pointer to the openchangedb message object \param row pointer to the SRow structure holding the array of properties to set on the message \return MAPI_E_SUCCESS on success, otherwise MAPI errors. */ _PUBLIC_ enum MAPISTATUS openchangedb_message_set_properties(TALLOC_CTX *mem_ctx, void *message_object, struct SRow *row) { struct openchangedb_message *msg = (struct openchangedb_message *) message_object; struct ldb_message *message; struct ldb_message_element *element; char *PidTagAttr = NULL; struct SPropValue value; char *str_value; int i; bool tofree = false; DEBUG(5, ("openchangedb_message_set_properties\n")); /* Sanity checks */ OPENCHANGE_RETVAL_IF(!msg, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!row, MAPI_E_NOT_INITIALIZED, NULL); /* Get results from correct location */ switch (msg->status) { case OPENCHANGEDB_MESSAGE_CREATE: OPENCHANGE_RETVAL_IF(!msg->msg, MAPI_E_NOT_INITIALIZED, NULL); message = msg->msg; break; case OPENCHANGEDB_MESSAGE_OPEN: OPENCHANGE_RETVAL_IF(!msg->res, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!msg->res->count, MAPI_E_NOT_INITIALIZED, NULL); message = msg->res->msgs[0]; break; default: return MAPI_E_INVALID_PARAMETER; } for (i = 0; i < row->cValues; i++) { tofree = false; value = row->lpProps[i]; switch (value.ulPropTag) { case PR_DEPTH: case PR_SOURCE_KEY: case PR_PARENT_SOURCE_KEY: case PR_CHANGE_KEY: DEBUG(5, ("Ignored attempt to set handled property %.8x\n", value.ulPropTag)); break; default: /* Convert proptag into PidTag attribute */ PidTagAttr = (char *) openchangedb_property_get_attribute(value.ulPropTag); if (!PidTagAttr) { PidTagAttr = talloc_asprintf(mem_ctx, "%.8x", value.ulPropTag); tofree = true; } str_value = openchangedb_set_folder_property_data((TALLOC_CTX *)message, &value); if (!str_value) { DEBUG(5, ("Ignored property of unhandled type %.4x\n", (value.ulPropTag & 0xFFFF))); continue; } else { element = ldb_msg_find_element(message, PidTagAttr); if (!element) { /* Case where the element doesn't exist */ ldb_msg_add_string(message, PidTagAttr, str_value); message->elements[message->num_elements - 1].flags = LDB_FLAG_MOD_ADD; } else { switch (msg->status) { case OPENCHANGEDB_MESSAGE_CREATE: ldb_msg_remove_element(message, element); ldb_msg_add_string(message, PidTagAttr, str_value); message->elements[message->num_elements - 1].flags = LDB_FLAG_MOD_ADD; break; case OPENCHANGEDB_MESSAGE_OPEN: if (element->flags == LDB_FLAG_MOD_ADD) { ldb_msg_remove_element(message, element); ldb_msg_add_string(message, PidTagAttr, str_value); message->elements[message->num_elements - 1].flags = LDB_FLAG_MOD_ADD; } else { ldb_msg_remove_element(message, element); ldb_msg_add_string(message, PidTagAttr, str_value); message->elements[message->num_elements - 1].flags = LDB_FLAG_MOD_REPLACE; } break; } } } if (tofree == true) { talloc_free((char *)PidTagAttr); } break; } } DEBUG(5, ("openchangedb_message_set_properties end\n")); return MAPI_E_SUCCESS; }
/* * complete a domain join, when joining to a AD domain: * 1.) connect and bind to the DRSUAPI pipe * 2.) do a DsCrackNames() to find the machine account dn * 3.) connect to LDAP * 4.) do an ldap search to find the "msDS-KeyVersionNumber" of the machine account * 5.) set the servicePrincipalName's of the machine account via LDAP, (maybe we should use DsWriteAccountSpn()...) * 6.) do a DsCrackNames() to find the domain dn * 7.) find out Site specific stuff, look at libnet_JoinSite() for details */ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_JoinDomain *r) { NTSTATUS status; TALLOC_CTX *tmp_ctx; const char *realm = r->out.realm; struct dcerpc_binding *samr_binding = r->out.samr_binding; struct dcerpc_pipe *drsuapi_pipe; struct dcerpc_binding *drsuapi_binding; struct drsuapi_DsBind r_drsuapi_bind; struct drsuapi_DsCrackNames r_crack_names; struct drsuapi_DsNameString names[1]; struct policy_handle drsuapi_bind_handle; struct GUID drsuapi_bind_guid; struct ldb_context *remote_ldb; struct ldb_dn *account_dn; const char *account_dn_str; const char *remote_ldb_url; struct ldb_result *res; struct ldb_message *msg; int ret, rtn; const char * const attrs[] = { "msDS-KeyVersionNumber", "servicePrincipalName", "dNSHostName", "objectGUID", NULL, }; r->out.error_string = NULL; /* We need to convert between a samAccountName and domain to a * DN in the directory. The correct way to do this is with * DRSUAPI CrackNames */ /* Fiddle with the bindings, so get to DRSUAPI on * NCACN_IP_TCP, sealed */ tmp_ctx = talloc_named(r, 0, "libnet_JoinADSDomain temp context"); if (!tmp_ctx) { r->out.error_string = NULL; return NT_STATUS_NO_MEMORY; } drsuapi_binding = talloc_zero(tmp_ctx, struct dcerpc_binding); if (!drsuapi_binding) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } *drsuapi_binding = *samr_binding; /* DRSUAPI is only available on IP_TCP, and locally on NCALRPC */ if (drsuapi_binding->transport != NCALRPC) { drsuapi_binding->transport = NCACN_IP_TCP; } drsuapi_binding->endpoint = NULL; drsuapi_binding->flags |= DCERPC_SEAL; status = dcerpc_pipe_connect_b(tmp_ctx, &drsuapi_pipe, drsuapi_binding, &ndr_table_drsuapi, ctx->cred, ctx->event_ctx, ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(r, "Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s", r->out.domain_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* get a DRSUAPI pipe handle */ GUID_from_string(DRSUAPI_DS_BIND_GUID, &drsuapi_bind_guid); r_drsuapi_bind.in.bind_guid = &drsuapi_bind_guid; r_drsuapi_bind.in.bind_info = NULL; r_drsuapi_bind.out.bind_handle = &drsuapi_bind_handle; status = dcerpc_drsuapi_DsBind_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_drsuapi_bind); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(r, "dcerpc_drsuapi_DsBind failed - %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) { r->out.error_string = talloc_asprintf(r, "DsBind failed - %s", win_errstr(r_drsuapi_bind.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } /* Actually 'crack' the names */ ZERO_STRUCT(r_crack_names); r_crack_names.in.bind_handle = &drsuapi_bind_handle; r_crack_names.in.level = 1; r_crack_names.in.req = talloc(r, union drsuapi_DsNameRequest); if (!r_crack_names.in.req) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } r_crack_names.in.req->req1.codepage = 1252; /* western european */ r_crack_names.in.req->req1.language = 0x00000407; /* german */ r_crack_names.in.req->req1.count = 1; r_crack_names.in.req->req1.names = names; r_crack_names.in.req->req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS; r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY; r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = dom_sid_string(tmp_ctx, r->out.account_sid); if (!names[0].str) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } r_crack_names.out.ctr = talloc(r, union drsuapi_DsNameCtr); r_crack_names.out.level_out = talloc(r, uint32_t); if (!r_crack_names.out.ctr || !r_crack_names.out.level_out) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(r, "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", names[0].str, nt_errstr(status)); talloc_free(tmp_ctx); return status; } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } else if (*r_crack_names.out.level_out != 1 || !r_crack_names.out.ctr->ctr1 || r_crack_names.out.ctr->ctr1->count != 1) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed"); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; } else if (r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr->ctr1->array[0].status); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } else if (r_crack_names.out.ctr->ctr1->array[0].result_name == NULL) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name"); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; } /* Store the DN of our machine account. */ account_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name; /* Now we know the user's DN, open with LDAP, read and modify a few things */ remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", drsuapi_binding->target_hostname); if (!remote_ldb_url) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } remote_ldb = ldb_wrap_connect(tmp_ctx, ctx->event_ctx, ctx->lp_ctx, remote_ldb_url, NULL, ctx->cred, 0); if (!remote_ldb) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } account_dn = ldb_dn_new(tmp_ctx, remote_ldb, account_dn_str); if (account_dn == NULL) { r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s", account_dn_str); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } /* search for the user's record */ ret = ldb_search(remote_ldb, tmp_ctx, &res, account_dn, LDB_SCOPE_BASE, attrs, NULL); if (ret != LDB_SUCCESS) { r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s", account_dn_str, ldb_errstring(remote_ldb)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } if (res->count != 1) { r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries", account_dn_str, res->count); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } /* Prepare a new message, for the modify */ msg = ldb_msg_new(tmp_ctx); if (!msg) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } msg->dn = res->msgs[0]->dn; { unsigned int i; const char *service_principal_name[2]; const char *dns_host_name = strlower_talloc(msg, talloc_asprintf(msg, "%s.%s", r->in.netbios_name, realm)); if (!dns_host_name) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } service_principal_name[0] = talloc_asprintf(msg, "HOST/%s", dns_host_name); service_principal_name[1] = talloc_asprintf(msg, "HOST/%s", r->in.netbios_name); for (i=0; i < ARRAY_SIZE(service_principal_name); i++) { if (!service_principal_name[i]) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = ldb_msg_add_string(msg, "servicePrincipalName", service_principal_name[i]); if (rtn != LDB_SUCCESS) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } } rtn = ldb_msg_add_string(msg, "dNSHostName", dns_host_name); if (rtn != LDB_SUCCESS) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = dsdb_replace(remote_ldb, msg, 0); if (rtn != LDB_SUCCESS) { r->out.error_string = talloc_asprintf(r, "Failed to replace entries on %s", ldb_dn_get_linearized(msg->dn)); talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } } msg = ldb_msg_new(tmp_ctx); if (!msg) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } msg->dn = res->msgs[0]->dn; rtn = samdb_msg_add_uint(remote_ldb, msg, msg, "msDS-SupportedEncryptionTypes", ENC_ALL_TYPES); if (rtn != LDB_SUCCESS) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } rtn = dsdb_replace(remote_ldb, msg, 0); /* The remote server may not support this attribute, if it * isn't a modern schema */ if (rtn != LDB_SUCCESS && rtn != LDB_ERR_NO_SUCH_ATTRIBUTE) { r->out.error_string = talloc_asprintf(r, "Failed to replace msDS-SupportedEncryptionTypes on %s", ldb_dn_get_linearized(msg->dn)); talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } /* DsCrackNames to find out the DN of the domain. */ r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = talloc_asprintf(tmp_ctx, "%s\\", r->out.domain_name); if (!names[0].str) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(r, "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", r->in.domain_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } else if (*r_crack_names.out.level_out != 1 || !r_crack_names.out.ctr->ctr1 || r_crack_names.out.ctr->ctr1->count != 1 || !r_crack_names.out.ctr->ctr1->array[0].result_name || r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { r->out.error_string = talloc_asprintf(r, "DsCrackNames failed"); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } /* Store the account DN. */ r->out.account_dn_str = account_dn_str; talloc_steal(r, account_dn_str); /* Store the domain DN. */ r->out.domain_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name; talloc_steal(r, r_crack_names.out.ctr->ctr1->array[0].result_name); /* Store the KVNO of the account, critical for some kerberos * operations */ r->out.kvno = ldb_msg_find_attr_as_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); /* Store the account GUID. */ r->out.account_guid = samdb_result_guid(res->msgs[0], "objectGUID"); if (r->in.acct_type == ACB_SVRTRUST) { status = libnet_JoinSite(ctx, remote_ldb, r); } talloc_free(tmp_ctx); return status; }
static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data) { struct ldb_message *msg; char *name_dup, *type_str; int ret; msg = talloc_zero(mem_ctx, struct ldb_message); if (msg == NULL) { return NULL; } name_dup = talloc_strdup(msg, name); if (name_dup == NULL) { talloc_free(msg); return NULL; } ret = ldb_msg_add_string(msg, "value", name_dup); if (ret != LDB_SUCCESS) { talloc_free(msg); return NULL; } switch (type) { case REG_SZ: case REG_EXPAND_SZ: if ((data.length > 0) && (data.data != NULL)) { struct ldb_val *val; bool ret2 = false; val = talloc_zero(msg, struct ldb_val); if (val == NULL) { talloc_free(msg); return NULL; } /* The data is provided as UTF16 string */ ret2 = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val->data, &val->length); if (ret2) { ret = ldb_msg_add_value(msg, "data", val, NULL); } else { /* workaround for non-standard data */ ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); } } else { ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); } break; case REG_DWORD: case REG_DWORD_BIG_ENDIAN: if ((data.length > 0) && (data.data != NULL)) { if (data.length == sizeof(uint32_t)) { char *conv_str; conv_str = talloc_asprintf(msg, "0x%8.8x", IVAL(data.data, 0)); if (conv_str == NULL) { talloc_free(msg); return NULL; } ret = ldb_msg_add_string(msg, "data", conv_str); } else { /* workaround for non-standard data */ talloc_free(msg); return NULL; } } else { ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); } break; case REG_QWORD: if ((data.length > 0) && (data.data != NULL)) { if (data.length == sizeof(uint64_t)) { char *conv_str; conv_str = talloc_asprintf(msg, "0x%16.16llx", (unsigned long long)BVAL(data.data, 0)); if (conv_str == NULL) { talloc_free(msg); return NULL; } ret = ldb_msg_add_string(msg, "data", conv_str); } else { /* workaround for non-standard data */ talloc_free(msg); return NULL; } } else { ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); } break; case REG_BINARY: default: if ((data.length > 0) && (data.data != NULL)) { ret = ldb_msg_add_value(msg, "data", &data, NULL); } else { ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); } break; }
/** \details Initialize and create a message object \param mem_ctx pointer to the memory context to use for allocation \param ldb_ctx pointer to the ldb context \param messageID the identifier of the message to create \param folderID the identifier of the folder where the message is created \param message_object pointer on pointer to the message object to return \return MAPI_E_SUCCESS on success, otherwise MAPI error */ _PUBLIC_ enum MAPISTATUS openchangedb_message_create(TALLOC_CTX *mem_ctx, struct ldb_context *ldb_ctx, uint64_t messageID, uint64_t folderID, bool fai, void **message_object) { enum MAPISTATUS retval; struct openchangedb_message *msg; struct ldb_dn *basedn; char *dn; char *parentDN; char *mailboxDN; int i; /* Sanity checks */ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!message_object, MAPI_E_NOT_INITIALIZED, NULL); /* Retrieve distinguishedName of parent folder */ retval = openchangedb_get_distinguishedName(mem_ctx, ldb_ctx, folderID, &parentDN); OPENCHANGE_RETVAL_IF(retval, retval, NULL); /* Retrieve mailboxDN of parent folder */ retval = openchangedb_get_mailboxDN(mem_ctx, ldb_ctx, folderID, &mailboxDN); if (retval) { mailboxDN = NULL; } dn = talloc_asprintf(mem_ctx, "CN=%"PRIu64",%s", messageID, parentDN); OPENCHANGE_RETVAL_IF(!dn, MAPI_E_NOT_ENOUGH_MEMORY, NULL); basedn = ldb_dn_new(mem_ctx, ldb_ctx, dn); talloc_free(dn); OPENCHANGE_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, NULL); msg = talloc_zero(mem_ctx, struct openchangedb_message); OPENCHANGE_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_MEMORY, NULL); msg->status = OPENCHANGEDB_MESSAGE_CREATE; msg->folderID = folderID; msg->messageID = messageID; msg->ldb_ctx = ldb_ctx; msg->msg = NULL; msg->res = NULL; msg->msg = ldb_msg_new((TALLOC_CTX *)msg); OPENCHANGE_RETVAL_IF(!msg->msg, MAPI_E_NOT_ENOUGH_MEMORY, msg); msg->msg->dn = ldb_dn_copy((TALLOC_CTX *)msg->msg, basedn); /* Add openchangedb required attributes */ ldb_msg_add_string(msg->msg, "objectClass", fai ? "faiMessage" : "systemMessage"); ldb_msg_add_fmt(msg->msg, "cn", "%"PRIu64, messageID); ldb_msg_add_fmt(msg->msg, "PidTagParentFolderId", "%"PRIu64, folderID); ldb_msg_add_fmt(msg->msg, "PidTagMessageId", "%"PRIu64, messageID); ldb_msg_add_fmt(msg->msg, "distinguishedName", "%s", ldb_dn_get_linearized(msg->msg->dn)); if (mailboxDN) { ldb_msg_add_string(msg->msg, "mailboxDN", mailboxDN); } /* Add required properties as described in [MS_OXCMSG] 3.2.5.2 */ ldb_msg_add_string(msg->msg, "PidTagDisplayBcc", ""); ldb_msg_add_string(msg->msg, "PidTagDisplayCc", ""); ldb_msg_add_string(msg->msg, "PidTagDisplayTo", ""); /* PidTagMessageSize */ /* PidTagSecurityDescriptor */ /* ldb_msg_add_string(msg->msg, "PidTagCreationTime", ""); */ /* ldb_msg_add_string(msg->msg, "PidTagLastModificationTime", ""); */ /* PidTagSearchKey */ /* PidTagMessageLocalId */ /* PidTagCreatorName */ /* PidTagCreatorEntryId */ ldb_msg_add_fmt(msg->msg, "PidTagHasNamedProperties", "%d", 0x0); /* PidTagLocaleId same as PidTagMessageLocaleId */ /* PidTagLocalCommitTime same as PidTagCreationTime */ /* Set LDB flag */ for (i = 0; i < msg->msg->num_elements; i++) { msg->msg->elements[i].flags = LDB_FLAG_MOD_ADD; } *message_object = (void *)msg; return MAPI_E_SUCCESS; }
static int acl_allowedAttributes(struct ldb_module *module, struct ldb_message *sd_msg, struct ldb_message *msg, struct acl_context *ac) { struct ldb_message_element *oc_el; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *mem_ctx; const char **attr_list; int i, ret; /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { return LDB_SUCCESS; } /* Must remove any existing attribute */ if (ac->allowedAttributes) { ldb_msg_remove_attr(msg, "allowedAttributes"); } mem_ctx = talloc_new(msg); if (!mem_ctx) { ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; } oc_el = ldb_msg_find_element(sd_msg, "objectClass"); attr_list = dsdb_full_attribute_list(mem_ctx, schema, oc_el, DSDB_SCHEMA_ALL); if (!attr_list) { ldb_asprintf_errstring(ldb, "acl: Failed to get list of attributes"); talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } if (ac->allowedAttributes) { for (i=0; attr_list && attr_list[i]; i++) { ldb_msg_add_string(msg, "allowedAttributes", attr_list[i]); } } if (ac->allowedAttributesEffective) { struct security_descriptor *sd; struct dom_sid *sid = NULL; ldb_msg_remove_attr(msg, "allowedAttributesEffective"); if (ac->user_type == SECURITY_SYSTEM) { for (i=0; attr_list && attr_list[i]; i++) { ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]); } return LDB_SUCCESS; } ret = get_sd_from_ldb_message(mem_ctx, sd_msg, &sd); if (ret != LDB_SUCCESS) { return ret; } ret = get_dom_sid_from_ldb_message(mem_ctx, sd_msg, &sid); if (ret != LDB_SUCCESS) { return ret; } for (i=0; attr_list && attr_list[i]; i++) { struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema, attr_list[i]); if (!attr) { return LDB_ERR_OPERATIONS_ERROR; } /* remove constructed attributes */ if (attr->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED || attr->systemOnly || (attr->linkID != 0 && attr->linkID % 2 != 0 )) { continue; } ret = acl_check_access_on_attribute(module, msg, sd, sid, SEC_ADS_WRITE_PROP, attr); if (ret == LDB_SUCCESS) { ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]); } } } return LDB_SUCCESS; }
int sysdb_check_upgrade_02(struct sss_domain_info *domains, const char *db_path) { TALLOC_CTX *tmp_ctx = NULL; struct ldb_context *ldb; char *ldb_file; struct sysdb_ctx *sysdb; struct sss_domain_info *dom; struct ldb_message_element *el; struct ldb_message *msg; struct ldb_result *res; struct ldb_dn *verdn; const char *version = NULL; bool do_02_upgrade = false; bool ctx_trans = false; int ret; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } ret = sysdb_get_db_file(tmp_ctx, "local", "UPGRADE", db_path, &ldb_file); if (ret != EOK) { goto exit; } ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); if (ret != EOK) { DEBUG(1, ("sysdb_ldb_connect failed.\n")); return ret; } verdn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); if (!verdn) { ret = EIO; goto exit; } ret = ldb_search(ldb, tmp_ctx, &res, verdn, LDB_SCOPE_BASE, NULL, NULL); if (ret != LDB_SUCCESS) { ret = EIO; goto exit; } if (res->count > 1) { ret = EIO; goto exit; } if (res->count == 1) { el = ldb_msg_find_element(res->msgs[0], "version"); if (el) { if (el->num_values != 1) { ret = EINVAL; goto exit; } version = talloc_strndup(tmp_ctx, (char *)(el->values[0].data), el->values[0].length); if (!version) { ret = ENOMEM; goto exit; } if (strcmp(version, SYSDB_VERSION) == 0) { /* all fine, return */ ret = EOK; goto exit; } DEBUG(4, ("Upgrading DB from version: %s\n", version)); if (strcmp(version, SYSDB_VERSION_0_1) == 0) { /* convert database */ ret = sysdb_upgrade_01(ldb, &version); if (ret != EOK) goto exit; } if (strcmp(version, SYSDB_VERSION_0_2) == 0) { /* need to convert database to split files */ do_02_upgrade = true; } } } if (!do_02_upgrade) { /* not a v2 upgrade, return and let the normal code take over any * further upgrade */ ret = EOK; goto exit; } /* == V2->V3 UPGRADE == */ DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3)); /* ldb uses posix locks, * posix is stupid and kills all locks when you close *any* file * descriptor associated to the same file. * Therefore we must close and reopen the ldb file here */ /* == Backup and reopen ldb == */ /* close */ talloc_zfree(ldb); /* backup*/ ret = backup_file(ldb_file, 0); if (ret != EOK) { goto exit; } /* reopen */ ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); if (ret != EOK) { DEBUG(1, ("sysdb_ldb_connect failed.\n")); return ret; } /* open a transaction */ ret = ldb_transaction_start(ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); ret = EIO; goto exit; } /* == Upgrade contents == */ for (dom = domains; dom; dom = dom->next) { struct ldb_dn *domain_dn; struct ldb_dn *users_dn; struct ldb_dn *groups_dn; int i; /* skip local */ if (strcasecmp(dom->provider, "local") == 0) { continue; } /* create new dom db */ ret = sysdb_domain_init_internal(tmp_ctx, dom, db_path, false, &sysdb); if (ret != EOK) { goto done; } ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); ret = EIO; goto done; } ctx_trans = true; /* search all entries for this domain in local, * copy them all in the new database, * then remove them from local */ domain_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, sysdb->domain->name); if (!domain_dn) { ret = ENOMEM; goto done; } ret = ldb_search(ldb, tmp_ctx, &res, domain_dn, LDB_SCOPE_SUBTREE, NULL, NULL); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } users_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_USER_BASE, sysdb->domain->name); if (!users_dn) { ret = ENOMEM; goto done; } groups_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_GROUP_BASE, sysdb->domain->name); if (!groups_dn) { ret = ENOMEM; goto done; } for (i = 0; i < res->count; i++) { struct ldb_dn *orig_dn; msg = res->msgs[i]; /* skip pre-created congtainers */ if ((ldb_dn_compare(msg->dn, domain_dn) == 0) || (ldb_dn_compare(msg->dn, users_dn) == 0) || (ldb_dn_compare(msg->dn, groups_dn) == 0)) { continue; } /* regenerate the DN against the new ldb as it may have different * casefolding rules (example: name changing from case insensitive * to case sensitive) */ orig_dn = msg->dn; msg->dn = ldb_dn_new(msg, sysdb->ldb, ldb_dn_get_linearized(orig_dn)); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_add(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { DEBUG(0, ("WARNING: Could not add entry %s," " to new ldb file! (%d [%s])\n", ldb_dn_get_linearized(msg->dn), ret, ldb_errstring(sysdb->ldb))); } ret = ldb_delete(ldb, orig_dn); if (ret != LDB_SUCCESS) { DEBUG(0, ("WARNING: Could not remove entry %s," " from old ldb file! (%d [%s])\n", ldb_dn_get_linearized(orig_dn), ret, ldb_errstring(ldb))); } } /* now remove the basic containers from local */ /* these were optional so debug at level 9 in case * of failure just for tracing */ ret = ldb_delete(ldb, groups_dn); if (ret != LDB_SUCCESS) { DEBUG(9, ("WARNING: Could not remove entry %s," " from old ldb file! (%d [%s])\n", ldb_dn_get_linearized(groups_dn), ret, ldb_errstring(ldb))); } ret = ldb_delete(ldb, users_dn); if (ret != LDB_SUCCESS) { DEBUG(9, ("WARNING: Could not remove entry %s," " from old ldb file! (%d [%s])\n", ldb_dn_get_linearized(users_dn), ret, ldb_errstring(ldb))); } ret = ldb_delete(ldb, domain_dn); if (ret != LDB_SUCCESS) { DEBUG(9, ("WARNING: Could not remove entry %s," " from old ldb file! (%d [%s])\n", ldb_dn_get_linearized(domain_dn), ret, ldb_errstring(ldb))); } ret = ldb_transaction_commit(sysdb->ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); ret = EIO; goto done; } ctx_trans = false; talloc_zfree(domain_dn); talloc_zfree(groups_dn); talloc_zfree(users_dn); talloc_zfree(res); } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = ldb_transaction_commit(ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); ret = EIO; goto exit; } ret = EOK; done: if (ret != EOK) { if (ctx_trans) { ret = ldb_transaction_cancel(sysdb->ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); } } ret = ldb_transaction_cancel(ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); } } exit: talloc_free(tmp_ctx); return ret; }
static int acl_childClassesEffective(struct ldb_module *module, struct ldb_message *sd_msg, struct ldb_message *msg, struct acl_context *ac) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses = NULL; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; struct security_descriptor *sd; struct dom_sid *sid = NULL; int i, j, ret; if (ac->user_type == SECURITY_SYSTEM) { return acl_childClasses(module, sd_msg, msg, "allowedChildClassesEffective"); } /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { return LDB_SUCCESS; } /* Must remove any existing attribute, or else confusion reins */ ldb_msg_remove_attr(msg, "allowedChildClassesEffective"); oc_el = ldb_msg_find_element(sd_msg, "objectClass"); ret = get_sd_from_ldb_message(msg, sd_msg, &sd); if (ret != LDB_SUCCESS) { return ret; } ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid); if (ret != LDB_SUCCESS) { return ret; } for (i=0; oc_el && i < oc_el->num_values; i++) { sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { /* We don't know this class? what is going on? */ continue; } for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { ret = acl_check_access_on_class(module, msg, sd, sid, SEC_ADS_CREATE_CHILD, sclass->possibleInferiors[j]); if (ret == LDB_SUCCESS) { ldb_msg_add_string(msg, "allowedChildClassesEffective", sclass->possibleInferiors[j]); } } } allowedClasses = ldb_msg_find_element(msg, "allowedChildClassesEffective"); if (!allowedClasses) { return LDB_SUCCESS; } if (allowedClasses->num_values > 1) { qsort(allowedClasses->values, allowedClasses->num_values, sizeof(*allowedClasses->values), (comparison_fn_t)data_blob_cmp); for (i=1 ; i < allowedClasses->num_values; i++) { struct ldb_val *val1 = &allowedClasses->values[i-1]; struct ldb_val *val2 = &allowedClasses->values[i]; if (data_blob_cmp(val1, val2) == 0) { memmove(val1, val2, (allowedClasses->num_values - i) * sizeof( struct ldb_val)); allowedClasses->num_values--; i--; } } } return LDB_SUCCESS; }
int sysdb_upgrade_03(struct sysdb_ctx *sysdb, const char **ver) { TALLOC_CTX *tmp_ctx; int ret; struct ldb_message *msg; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_4)); ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } /* Make this database case-sensitive */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_DELETE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_4); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_4, ver); talloc_free(tmp_ctx); return ret; }
static errno_t sysdb_svc_update(struct sysdb_ctx *sysdb, struct ldb_dn *dn, int port, const char **aliases, const char **protocols) { errno_t ret; struct ldb_message *msg; int lret; unsigned int i; if (!dn || !protocols || !protocols[0]) { return EINVAL; } msg = ldb_msg_new(NULL); if (!msg) { ret = ENOMEM; goto done; } msg->dn = dn; /* Update the port */ ret = add_ulong(msg, SYSDB_MOD_REP, SYSDB_SVC_PORT, port); if (ret != EOK) goto done; if (aliases && aliases[0]) { /* Update the aliases */ lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, SYSDB_MOD_REP, NULL); if (lret != LDB_SUCCESS) { ret = ENOMEM; goto done; } for (i = 0; aliases[i]; i++) { lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]); if (lret != LDB_SUCCESS) { ret = EINVAL; goto done; } } } /* Update the protocols */ lret = ldb_msg_add_empty(msg, SYSDB_SVC_PROTO, SYSDB_MOD_REP, NULL); if (lret != LDB_SUCCESS) { ret = ENOMEM; goto done; } for (i = 0; protocols[i]; i++) { lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]); if (lret != LDB_SUCCESS) { ret = EINVAL; goto done; } } lret = ldb_modify(sysdb->ldb, msg); if (lret != LDB_SUCCESS) { DEBUG(SSSDBG_MINOR_FAILURE, "ldb_modify failed: [%s](%d)[%s]\n", ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)); } ret = sysdb_error_to_errno(lret); done: if (ret) { DEBUG(SSSDBG_TRACE_INTERNAL, "Error: %d (%s)\n", ret, strerror(ret)); } talloc_free(msg); return ret; }
int sysdb_upgrade_04(struct sysdb_ctx *sysdb, const char **ver) { TALLOC_CTX *tmp_ctx; int ret; struct ldb_message *msg; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_5)); ret = ldb_transaction_start(sysdb->ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; } /* Add new index */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "@IDXATTR", "originalDN"); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } /* Rebuild memberuid and memberoif attributes */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@MEMBEROF-REBUILD"); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_add(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } /* conversion done, upgrade version number */ msg = ldb_msg_new(tmp_ctx); if (!msg) { ret = ENOMEM; goto done; } msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); if (!msg->dn) { ret = ENOMEM; goto done; } ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_5); if (ret != LDB_SUCCESS) { ret = ENOMEM; goto done; } ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } ret = EOK; done: ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_5, ver); talloc_free(tmp_ctx); return ret; }