} 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); }
/** \details return the mapped property ID matching the nameid structure passed in parameter. \param ldb_ctx pointer to the namedprops ldb context \param nameid the MAPINAMEID structure to lookup \param propID pointer to the property ID the function returns \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR */ _PUBLIC_ enum mapistore_error mapistore_namedprops_create_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t mapped_id) { int ret; TALLOC_CTX *mem_ctx; char *ldif_record; struct ldb_ldif *ldif; char *hex_id, *dec_id, *dec_mappedid, *guid; struct ldb_message *normalized_msg; const char *ldif_records[] = { NULL, NULL }; mem_ctx = talloc_zero(NULL, TALLOC_CTX); dec_mappedid = talloc_asprintf(mem_ctx, "%u", mapped_id); guid = GUID_string(mem_ctx, &nameid.lpguid); switch (nameid.ulKind) { case MNID_ID: hex_id = talloc_asprintf(mem_ctx, "%.4x", nameid.kind.lid); dec_id = talloc_asprintf(mem_ctx, "%u", nameid.kind.lid); ldif_record = talloc_asprintf(mem_ctx, "dn: CN=0x%s,CN=%s,CN=default\nobjectClass: MNID_ID\ncn: 0x%s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropId: %s\n", hex_id, guid, hex_id, guid, dec_mappedid, dec_id); break; case MNID_STRING: ldif_record = talloc_asprintf(mem_ctx, "dn: CN=%s,CN=%s,CN=default\nobjectClass: MNID_STRING\ncn: %s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropName: %s\n", nameid.kind.lpwstr.Name, guid, nameid.kind.lpwstr.Name, guid, dec_mappedid, nameid.kind.lpwstr.Name); break; default: abort(); } DEBUG(5, ("inserting record:\n%s\n", ldif_record)); ldif_records[0] = ldif_record; ldif = ldb_ldif_read_string(ldb_ctx, ldif_records); ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg); MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL); ret = ldb_add(ldb_ctx, normalized_msg); talloc_free(normalized_msg); if (ret != LDB_SUCCESS) { MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL); } /* we invalidate the cache, if present */ if (nameids_cache) { talloc_free(nameids_cache); nameids_cache = NULL; } return ret; }
/** * Canonicalize a message, merging elements of the same name */ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, const struct ldb_message *msg) { int ret; struct ldb_message *msg2; /* * Preserve previous behavior and allocate * *msg2 into *ldb context */ ret = ldb_msg_normalize(ldb, ldb, msg, &msg2); if (ret != LDB_SUCCESS) { return NULL; } return msg2; }
/* add records from an opened file */ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) { struct ldb_ldif *ldif; int fun_ret = LDB_SUCCESS, ret; struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); struct ldif_read_file_state state = { .f = f }; if (options->controls != NULL && req_ctrls== NULL) { printf("parsing controls failed: %s\n", ldb_errstring(ldb)); return LDB_ERR_OPERATIONS_ERROR; } fun_ret = ldb_transaction_start(ldb); if (fun_ret != LDB_SUCCESS) { fprintf(stderr, "ERR: (%s) on transaction start\n", ldb_errstring(ldb)); return fun_ret; } while ((ldif = ldb_ldif_read_file_state(ldb, &state))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); break; } ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &ldif->msg); if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: Message canonicalize failed - %s\n", ldb_strerror(ret)); fun_ret = ret; ldb_ldif_read_free(ldb, ldif); continue; } ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); if (ret != LDB_SUCCESS) { fprintf(stderr, "ERR: %s : \"%s\" on DN %s at block before line %llu\n", ldb_strerror(ret), ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn), (unsigned long long)state.line_no); fun_ret = ret; } else { (*count)++; if (options->verbose) { printf("Added %s\n", ldb_dn_get_linearized(ldif->msg->dn)); } } ldb_ldif_read_free(ldb, ldif); if (ret) { break; } } if (fun_ret == LDB_SUCCESS && !feof(f)) { fprintf(stderr, "Failed to parse ldif\n"); fun_ret = LDB_ERR_OPERATIONS_ERROR; } if (fun_ret == LDB_SUCCESS) { fun_ret = ldb_transaction_commit(ldb); if (fun_ret != LDB_SUCCESS) { fprintf(stderr, "ERR: (%s) on transaction commit\n", ldb_errstring(ldb)); } } else { ldb_transaction_cancel(ldb); } return fun_ret; }
WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df, const char *dn) { struct ldb_ldif *ldif; struct ldb_message *msg; TALLOC_CTX *mem_ctx; WERROR status; int ret; struct dsdb_schema *schema; const struct ldb_val *prefix_val; const struct ldb_val *info_val; struct ldb_val info_val_default; mem_ctx = talloc_new(ldb); if (!mem_ctx) { goto nomem; } schema = dsdb_new_schema(mem_ctx); if (!schema) { goto nomem; } schema->base_dn = ldb_dn_new(schema, ldb, dn); if (!schema->base_dn) { goto nomem; } schema->fsmo.we_are_master = true; schema->fsmo.update_allowed = true; schema->fsmo.master_dn = ldb_dn_new(schema, ldb, "@PROVISION_SCHEMA_MASTER"); if (!schema->fsmo.master_dn) { goto nomem; } /* * load the prefixMap attribute from pf */ ldif = ldb_ldif_read_string(ldb, &pf); if (!ldif) { status = WERR_INVALID_PARAM; goto failed; } talloc_steal(mem_ctx, ldif); ret = ldb_msg_normalize(ldb, mem_ctx, ldif->msg, &msg); if (ret != LDB_SUCCESS) { goto nomem; } talloc_free(ldif); prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap"); if (!prefix_val) { status = WERR_INVALID_PARAM; goto failed; } info_val = ldb_msg_find_ldb_val(msg, "schemaInfo"); if (!info_val) { status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default); W_ERROR_NOT_OK_GOTO(status, failed); info_val = &info_val_default; } status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val); if (!W_ERROR_IS_OK(status)) { DEBUG(0,("ERROR: dsdb_load_oid_mappings_ldb() failed with %s\n", win_errstr(status))); goto failed; } /* load the attribute and class definitions out of df */ while ((ldif = ldb_ldif_read_string(ldb, &df))) { talloc_steal(mem_ctx, ldif); ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &msg); if (ret != LDB_SUCCESS) { goto nomem; } status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg); talloc_free(ldif); if (!W_ERROR_IS_OK(status)) { goto failed; } } ret = dsdb_set_schema(ldb, schema); if (ret != LDB_SUCCESS) { status = WERR_FOOBAR; goto failed; } ret = dsdb_schema_fill_extended_dn(ldb, schema); if (ret != LDB_SUCCESS) { status = WERR_FOOBAR; goto failed; } goto done; nomem: status = WERR_NOMEM; failed: done: talloc_free(mem_ctx); return status; }
/** \details Initialize the named properties database or return pointer to the existing one if already initialized/opened. \param mem_ctx pointer to the memory context \param ldb_ctx pointer on pointer to the ldb context the function returns \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error */ enum mapistore_error mapistore_namedprops_init(TALLOC_CTX *mem_ctx, struct ldb_context **_ldb_ctx) { int ret; struct stat sb; struct ldb_context *ldb_ctx = NULL; struct ldb_ldif *ldif; char *filename; FILE *f; struct tevent_context *ev; char *database; /* Sanity checks */ MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL); MAPISTORE_RETVAL_IF(!_ldb_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL); ev = tevent_context_init(mem_ctx); MAPISTORE_RETVAL_IF(!ev, MAPISTORE_ERR_NO_MEMORY, NULL); database = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAMED); DEBUG(0, ("database = %s\n", database)); /* Step 1. Stat the database and populate it if it doesn't exist */ if (stat(database, &sb) == -1) { ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0); talloc_free(database); MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL); filename = talloc_asprintf(mem_ctx, "%s/mapistore_namedprops.ldif", mapistore_namedprops_get_ldif_path()); f = fopen(filename, "r"); talloc_free(filename); MAPISTORE_RETVAL_IF(!f, MAPISTORE_ERROR, NULL); ldb_transaction_start(ldb_ctx); while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) { struct ldb_message *normalized_msg; ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg); MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL); ret = ldb_add(ldb_ctx, normalized_msg); talloc_free(normalized_msg); if (ret != LDB_SUCCESS) { fclose(f); MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL); } ldb_ldif_read_free(ldb_ctx, ldif); } ldb_transaction_commit(ldb_ctx); fclose(f); } else { ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0); talloc_free(database); MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL); } *_ldb_ctx = ldb_ctx; return MAPISTORE_SUCCESS; }
/** \details Initialize the database and provision it \param conn pointer to the MySQL context \param schema_path pointer to the path holding schema files \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error */ static enum mapistore_error initialize_database(MYSQL *conn, const char *schema_path) { TALLOC_CTX *mem_ctx; enum mapistore_error retval = MAPISTORE_SUCCESS; struct ldb_context *ldb_ctx; struct ldb_ldif *ldif; struct ldb_message *msg; int ret; char *filename; FILE *f; bool inserted; bool schema_created; /* Sanity checks */ MAPISTORE_RETVAL_IF(!conn, MAPISTORE_ERR_DATABASE_INIT, NULL); mem_ctx = talloc_named(NULL, 0, "initialize_database"); MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_NO_MEMORY, NULL); filename = talloc_asprintf(mem_ctx, "%s/" NAMEDPROPS_MYSQL_SCHEMA, schema_path ? schema_path : mapistore_namedprops_get_ldif_path()); MAPISTORE_RETVAL_IF(!filename, MAPISTORE_ERR_NO_MEMORY, mem_ctx); schema_created = create_schema(conn, filename); if (!schema_created) { DEBUG(1, ("Failed named properties schema creation, " "last mysql error was: `%s`\n", mysql_error(conn))); MAPISTORE_RETVAL_ERR(MAPISTORE_ERR_DATABASE_INIT, mem_ctx); } ldb_ctx = ldb_init(mem_ctx, NULL); MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_BACKEND_INIT, mem_ctx); filename = talloc_asprintf(mem_ctx, "%s/mapistore_namedprops.ldif", schema_path ? schema_path : mapistore_namedprops_get_ldif_path()); MAPISTORE_RETVAL_IF(!filename, MAPISTORE_ERR_NO_MEMORY, mem_ctx); f = fopen(filename, "r"); talloc_free(filename); MAPISTORE_RETVAL_IF(!f, MAPISTORE_ERR_BACKEND_INIT, mem_ctx); while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) { ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &msg); if (ret) { retval = MAPISTORE_ERR_DATABASE_INIT; mapistore_set_errno(MAPISTORE_ERR_DATABASE_INIT); goto end; } inserted = insert_ldif_msg(conn, msg); ldb_ldif_read_free(ldb_ctx, ldif); if (!inserted) { retval = MAPISTORE_ERR_DATABASE_OPS; mapistore_set_errno(MAPISTORE_ERR_DATABASE_OPS); goto end; } } end: talloc_free(mem_ctx); fclose(f); return retval; }