} END_TEST START_TEST(test_call_get_MailboxReplica) { uint16_t ReplID; struct GUID ReplGUID; CHECK_SUCCESS(openchangedb_get_MailboxReplica(oc_ctx, "recipient", &ReplID, &ReplGUID)); ck_assert_int_eq(functions_called.get_MailboxReplica, 1); } END_TEST
} END_TEST START_TEST(test_call_get_MailboxReplica) { uint16_t ReplID; struct GUID local_guid = GUID_zero(); struct GUID ReplGUID; CHECK_SUCCESS(openchangedb_get_MailboxReplica(oc_ctx, "recipient", &ReplID, &ReplGUID)); ck_assert_int_eq(functions_called.get_MailboxReplica, 1); ck_assert_int_eq(ReplID, 0x03); ck_assert(GUID_equal(&ReplGUID, &local_guid)); } END_TEST
} END_TEST START_TEST (test_get_MailboxReplica) { TALLOC_CTX *local_mem_ctx = talloc_new(NULL); struct GUID *repl = talloc_zero(local_mem_ctx, struct GUID); struct GUID *expected_repl = talloc_zero(local_mem_ctx, struct GUID); uint16_t *repl_id = talloc_zero(local_mem_ctx, uint16_t); retval = openchangedb_get_MailboxReplica(g_oc_ctx, USER1, repl_id, repl); CHECK_SUCCESS; GUID_from_string("d87292c1-1bc3-4370-a734-98b559b69a52", expected_repl); ck_assert(GUID_equal(expected_repl, repl)); ck_assert_int_eq(*repl_id, 1); talloc_free(local_mem_ctx); } END_TEST
/** \details Check if the authenticated user belongs to the Exchange organization and is enabled \param dce_call pointer to the session context \param emsmdbp_ctx pointer to the EMSMDBP context \return true on success, otherwise false */ _PUBLIC_ bool emsmdbp_verify_user(struct dcesrv_call_state *dce_call, struct emsmdbp_context *emsmdbp_ctx) { int ret; const char *username = NULL; int msExchUserAccountControl; struct ldb_result *res = NULL; const char * const recipient_attrs[] = { "msExchUserAccountControl", NULL }; username = dcesrv_call_account_name(dce_call); ret = ldb_search(emsmdbp_ctx->samdb_ctx, emsmdbp_ctx, &res, ldb_get_default_basedn(emsmdbp_ctx->samdb_ctx), LDB_SCOPE_SUBTREE, recipient_attrs, "sAMAccountName=%s", ldb_binary_encode_string(emsmdbp_ctx, username)); /* If the search failed */ if (ret != LDB_SUCCESS || !res->count) { return false; } /* If msExchUserAccountControl attribute is not found */ if (!res->msgs[0]->num_elements) { return false; } /* If the attribute exists check its value */ msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2); if (msExchUserAccountControl == 2) { return false; } /* Get a copy of the username for later use and setup missing conn_info components */ emsmdbp_ctx->username = talloc_strdup(emsmdbp_ctx, username); openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &emsmdbp_ctx->mstore_ctx->conn_info->repl_id, &emsmdbp_ctx->mstore_ctx->conn_info->replica_guid); return true; }
_PUBLIC_ int emsmdbp_replid_to_guid(struct emsmdbp_context *emsmdbp_ctx, const char *username, const uint16_t replid, struct GUID *guidP) { uint16_t db_replid; struct GUID guid; if (replid == 2) { *guidP = MagicGUID; return MAPI_E_SUCCESS; } openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, username, &db_replid, &guid); if (replid == db_replid) { *guidP = guid; return MAPI_E_SUCCESS; } if (mapistore_replica_mapping_replid_to_guid(emsmdbp_ctx->mstore_ctx, username, replid, &guid) == MAPISTORE_SUCCESS) { *guidP = guid; return MAPI_E_SUCCESS; } return MAPI_E_NOT_FOUND; }
_PUBLIC_ int emsmdbp_guid_to_replid(struct emsmdbp_context *emsmdbp_ctx, const char *username, const struct GUID *guidP, uint16_t *replidP) { uint16_t replid; struct GUID guid; if (GUID_equal(guidP, MagicGUIDp)) { *replidP = 2; return MAPI_E_SUCCESS; } openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, username, &replid, &guid); if (GUID_equal(guidP, &guid)) { *replidP = replid; return MAPI_E_SUCCESS; } if (mapistore_replica_mapping_guid_to_replid(emsmdbp_ctx->mstore_ctx, username, guidP, &replid) == MAPISTORE_SUCCESS) { *replidP = replid; return MAPI_E_SUCCESS; } return MAPI_E_NOT_FOUND; }
/** \details Check if a fid is an special following [MS-OXOSFLD] Section 2.2.2 rules. \param emsmdbp_ctx pointer to the emsmdb provider context \param fid the folder identifier to check \return true on success, otherwise false \note An error on any call is interpreted as false */ _PUBLIC_ bool oxosfld_is_special_folder(struct emsmdbp_context *emsmdbp_ctx, uint64_t fid) { bool ret = false; struct Binary_r *entry_id; struct BinaryArray_r *entries_ids; struct FolderEntryId folder_entry_id; int i, system_idx; enum MAPISTATUS retval; TALLOC_CTX *local_mem_ctx; const uint32_t identification_properties[] = { PidTagIpmAppointmentEntryId, PidTagIpmContactEntryId, PidTagIpmJournalEntryId, PidTagIpmNoteEntryId, PidTagIpmTaskEntryId, PidTagRemindersOnlineEntryId, PidTagIpmDraftsEntryId }; const uint32_t IDENTIFICATION_PROP_COUNT = sizeof(identification_properties)/sizeof(uint32_t); const uint32_t ADDITIONAL_REN_ENTRY_IDS_COUNT = 5, FREEBUSY_DATA_ENTRYID_IDX = 3; uint64_t inbox_fid, mailbox_fid; /* Sanity checks */ if (!emsmdbp_ctx) return false; /* 1. The fids returned in RopLogon are special folders, as they are set with SystemIdx higher than -1. See emsmdbp_provisioning.c for details */ retval = openchangedb_get_system_idx(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, fid, &system_idx); if (retval == MAPI_E_SUCCESS && system_idx > -1) { OC_DEBUG(5, "Fid 0x%"PRIx64 " is a system special folder whose system_idx is %d", fid, system_idx); return true; } retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, EMSMDBP_MAILBOX_ROOT, &mailbox_fid); if (retval == MAPI_E_SUCCESS && mailbox_fid == fid) { OC_DEBUG(5, "Fid 0x%"PRIx64 " is the mailbox ID", fid); return true; } /* 2. Set of binary properties on the root folder or inbox folder */ /* TODO: work in Delegate mode */ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, EMSMDBP_INBOX, &inbox_fid); if (retval != MAPI_E_SUCCESS) { return false; } memset(&folder_entry_id, 0, sizeof(struct FolderEntryId)); retval = openchangedb_get_MailboxGuid(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &folder_entry_id.ProviderUID); if (retval != MAPI_E_SUCCESS) { return false; } retval = openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, NULL, &folder_entry_id.FolderDatabaseGuid); if (retval != MAPI_E_SUCCESS) { return false; } local_mem_ctx = talloc_new(NULL); if (!local_mem_ctx) return false; for (i = 0; i < IDENTIFICATION_PROP_COUNT; i++) { retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, identification_properties[i], inbox_fid, (void **) &entry_id); if (retval == MAPI_E_SUCCESS && fid_in_entry_id(entry_id, inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found in %s property", fid, get_proptag_name(identification_properties[i])); ret = true; goto end; } } /* 3. The PidTagAdditionalRenEntryIds contains an array of entry IDs with special folders */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagAdditionalRenEntryIds, inbox_fid, (void **) &entries_ids); if (retval == MAPI_E_SUCCESS && entries_ids && entries_ids->cValues >= ADDITIONAL_REN_ENTRY_IDS_COUNT) { for (i = 0; i < ADDITIONAL_REN_ENTRY_IDS_COUNT; i++) { if (fid_in_entry_id((entries_ids->lpbin + i), inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as %d index in PidTagAdditionalRenEntryIds", fid, i); ret = true; goto end; } } } /* 4. The PidTagAdditionalRenEntryIdsEx on the store object */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagAdditionalRenEntryIdsEx, inbox_fid, (void **) &entry_id); if (retval == MAPI_E_SUCCESS) { int j, k; struct PersistDataArray *persist_data_array; persist_data_array = get_PersistDataArray(local_mem_ctx, entry_id); if (persist_data_array && persist_data_array->cValues > 0) { struct Binary_r checked_entry_id; DATA_BLOB checked_folder_entry_id; struct PersistData persist_data; struct PersistElement persist_element; struct PersistElementArray persist_element_array; for (j = 0; j < persist_data_array->cValues; j++) { persist_data = persist_data_array->lpPersistData[j]; if (persist_data.PersistID == PERSIST_SENTINEL) { /* This is the last PersistData */ break; } persist_element_array = persist_data.DataElements; for (k = 0; k < persist_element_array.cValues; k++) { persist_element = persist_element_array.lpPersistElement[k]; if (persist_element.ElementID == PERSIST_SENTINEL) { /* This is the last PersistElement */ break; } if (persist_element.ElementID == RSF_ELID_ENTRYID) { checked_folder_entry_id = persist_element.ElementData.rsf_elid_entryid; checked_entry_id.cb = checked_folder_entry_id.length; checked_entry_id.lpb = checked_folder_entry_id.data; if (fid_in_entry_id(&checked_entry_id, inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as %d entry in PidTagAdditionalRenEntryIdsEx", fid, persist_data.PersistID); ret = true; goto end; } } } } } else { OC_DEBUG(5, "Cannot parse PersistDataArray"); } } /* 5. The entry ID indexed by 3 in PidTagFreeBusyEntryIds on the root folder stores the Freebusy data folder */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagFreeBusyEntryIds, inbox_fid, (void **) &entries_ids); if (retval == MAPI_E_SUCCESS && entries_ids && entries_ids->cValues >= FREEBUSY_DATA_ENTRYID_IDX && fid_in_entry_id((entries_ids->lpbin + FREEBUSY_DATA_ENTRYID_IDX), mailbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as Freebusy Data\n", fid); ret = true; goto end; } /* 6. The FID returned by RopGetReceiveFolder */ /* According to [MS-OXOSFLD] Section 2.2.7, we should search for the default Receive folder for the Store object. And according to [MS-OXCSTOR] Section 3.2.5.2, it should be the user's inbox folder and it is already checked above. */ end: talloc_free(local_mem_ctx); return ret; }