/** \details Build an EphemeralEntryID structure \param emsabp_ctx pointer to the EMSABP context \param DisplayType the AB object display type \param MId the MId value \param ephEntryID pointer to the EphemeralEntryID returned by the function \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_ENOUGH_RESOURCES or MAPI_E_CORRUPT_STORE */ _PUBLIC_ enum MAPISTATUS emsabp_set_EphemeralEntryID(struct emsabp_context *emsabp_ctx, uint32_t DisplayType, uint32_t MId, struct EphemeralEntryID *ephEntryID) { struct GUID *guid = (struct GUID *) NULL; /* Sanity checks */ OPENCHANGE_RETVAL_IF(!ephEntryID, MAPI_E_NOT_ENOUGH_RESOURCES, NULL); guid = (struct GUID *) samdb_ntds_objectGUID(emsabp_ctx->samdb_ctx); OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, NULL); ephEntryID->ID_type = 0x87; ephEntryID->R1 = 0x0; ephEntryID->R2 = 0x0; ephEntryID->R3 = 0x0; ephEntryID->ProviderUID.ab[0] = (guid->time_low & 0xFF); ephEntryID->ProviderUID.ab[1] = ((guid->time_low >> 8) & 0xFF); ephEntryID->ProviderUID.ab[2] = ((guid->time_low >> 16) & 0xFF); ephEntryID->ProviderUID.ab[3] = ((guid->time_low >> 24) & 0xFF); ephEntryID->ProviderUID.ab[4] = (guid->time_mid & 0xFF); ephEntryID->ProviderUID.ab[5] = ((guid->time_mid >> 8) & 0xFF); ephEntryID->ProviderUID.ab[6] = (guid->time_hi_and_version & 0xFF); ephEntryID->ProviderUID.ab[7] = ((guid->time_hi_and_version >> 8) & 0xFF); memcpy(ephEntryID->ProviderUID.ab + 8, guid->clock_seq, sizeof (uint8_t) * 2); memcpy(ephEntryID->ProviderUID.ab + 10, guid->node, sizeof (uint8_t) * 6); ephEntryID->R4 = 0x1; ephEntryID->DisplayType = DisplayType; ephEntryID->MId = MId; return MAPI_E_SUCCESS; }
static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args) { PyObject *py_ldb, *result; struct ldb_context *ldb; const struct GUID *guid; char *retstr; if (!PyArg_ParseTuple(args, "O", &py_ldb)) { return NULL; } PyErr_LDB_OR_RAISE(py_ldb, ldb); guid = samdb_ntds_objectGUID(ldb); if (guid == NULL) { PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID"); return NULL; } retstr = GUID_string(NULL, guid); if (retstr == NULL) { PyErr_NoMemory(); return NULL; } result = PyString_FromString(retstr); talloc_free(retstr); return result; }
static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct loadparm_context *lp_ctx) { const struct GUID *ntds_guid; struct drsuapi_DsBindInfo28 *bind_info28; service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info); if (!service->samdb) { return WERR_DS_UNAVAILABLE; } ntds_guid = samdb_ntds_objectGUID(service->samdb); if (!ntds_guid) { return WERR_DS_UNAVAILABLE; } service->ntds_guid = *ntds_guid; bind_info28 = &service->bind_info28; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_00100000; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; #if 0 /* we don't support XPRESS compression yet */ bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; #endif /* TODO: fill in site_guid */ bind_info28->site_guid = GUID_zero(); /* TODO: find out how this is really triggered! */ bind_info28->pid = 0; bind_info28->repl_epoch = 0; return WERR_OK; }
/* connect to the local SAM */ static WERROR kccsrv_connect_samdb(struct kccsrv_service *service, struct loadparm_context *lp_ctx) { const struct GUID *ntds_guid; service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info); if (!service->samdb) { return WERR_DS_UNAVAILABLE; } ntds_guid = samdb_ntds_objectGUID(service->samdb); if (!ntds_guid) { return WERR_DS_UNAVAILABLE; } service->ntds_guid = *ntds_guid; return WERR_OK; }
/* connect to the local SAM */ static WERROR kccsrv_connect_samdb(struct kccsrv_service *service, struct loadparm_context *lp_ctx) { const struct GUID *ntds_guid; service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info, 0); if (!service->samdb) { return WERR_DS_UNAVAILABLE; } ntds_guid = samdb_ntds_objectGUID(service->samdb); if (!ntds_guid) { return WERR_DS_UNAVAILABLE; } service->ntds_guid = *ntds_guid; if (samdb_rodc(service->samdb, &service->am_rodc) != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to determine RODC status\n")); return WERR_DS_UNAVAILABLE; } return WERR_OK; }
/** \details exchange_nsp NspiBind (0x0) function, Initiates a NSPI session with the client. This function checks if the user is an Exchange user and input parameters like codepage are valid. If it passes the tests, the function initializes an emsabp context and returns to the client a valid policy_handle and expected reply parameters. \param dce_call pointer to the session context \param mem_ctx pointer to the memory context \param r pointer to the NspiBind call structure \return MAPI_E_SUCCESS on success, otherwise a MAPI error */ static void dcesrv_NspiBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct NspiBind *r) { struct GUID *guid = (struct GUID *) NULL; struct emsabp_context *emsabp_ctx; struct dcesrv_handle *handle; struct policy_handle wire_handle; struct exchange_nsp_session *session; DEBUG(5, ("exchange_nsp: NspiBind (0x0)\n")); /* Step 0. Ensure incoming user is authenticated */ if (!dcesrv_call_authenticated(dce_call) && (r->in.dwFlags & fAnonymousLogin)) { DEBUG(1, ("No challenge requested by client, cannot authenticate\n")); wire_handle.handle_type = EXCHANGE_HANDLE_NSP; wire_handle.uuid = GUID_zero(); *r->out.handle = wire_handle; r->out.mapiuid = r->in.mapiuid; DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL); } /* Step 1. Initialize the emsabp context */ emsabp_ctx = emsabp_init(dce_call->conn->dce_ctx->lp_ctx, emsabp_tdb_ctx); if (!emsabp_ctx) { OC_ABORT(false, ("[exchange_nsp] Unable to initialize emsabp context")); wire_handle.handle_type = EXCHANGE_HANDLE_NSP; wire_handle.uuid = GUID_zero(); *r->out.handle = wire_handle; r->out.mapiuid = r->in.mapiuid; DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL); } if (lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "exchange_nsp", "debug", false)) { emsabp_enable_debug(emsabp_ctx); } /* Step 2. Check if incoming user belongs to the Exchange organization */ if ((emsabp_verify_user(dce_call, emsabp_ctx) == false) && (r->in.dwFlags & fAnonymousLogin)) { talloc_free(emsabp_ctx); wire_handle.handle_type = EXCHANGE_HANDLE_NSP; wire_handle.uuid = GUID_zero(); *r->out.handle = wire_handle; r->out.mapiuid = r->in.mapiuid; DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, emsabp_tdb_ctx); } /* Step 3. Check if valid cpID has been supplied */ if (emsabp_verify_codepage(emsabp_ctx, r->in.pStat->CodePage) == false) { talloc_free(emsabp_ctx); wire_handle.handle_type = EXCHANGE_HANDLE_NSP; wire_handle.uuid = GUID_zero(); *r->out.handle = wire_handle; r->out.mapiuid = r->in.mapiuid; DCESRV_NSP_RETURN(r, MAPI_E_UNKNOWN_CPID, emsabp_tdb_ctx); } /* Step 4. Retrieve OpenChange server GUID */ guid = (struct GUID *) samdb_ntds_objectGUID(emsabp_ctx->samdb_ctx); if (!guid) { DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, emsabp_ctx); } /* Step 5. Fill NspiBind reply */ handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_NSP); if (!handle) { DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx); } handle->data = (void *) emsabp_ctx; *r->out.handle = handle->wire_handle; r->out.mapiuid = guid; /* Search for an existing session and increment ref_count, otherwise create it */ session = dcesrv_find_nsp_session(&handle->wire_handle.uuid); if (session) { mpm_session_increment_ref_count(session->session); DEBUG(5, (" [unexpected]: existing nsp_session: %p; session: %p (ref++)\n", session, session->session)); } else { DEBUG(5, ("%s: Creating new session\n", __func__)); /* Step 6. Associate this emsabp context to the session */ session = talloc((TALLOC_CTX *)nsp_session, struct exchange_nsp_session); if (!session) { DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx); } session->session = mpm_session_init((TALLOC_CTX *)nsp_session, dce_call); if (!session->session) { DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx); } session->uuid = handle->wire_handle.uuid; mpm_session_set_private_data(session->session, (void *) emsabp_ctx); mpm_session_set_destructor(session->session, emsabp_destructor); DLIST_ADD_END(nsp_session, session, struct exchange_nsp_session *); } DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL); }
/* create a RID Set object for the specified DC */ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *rid_manager_dn, struct ldb_dn *ntds_dn, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *server_dn, *machine_dn, *rid_set_dn; int ret; struct ldb_message *msg; struct ldb_context *ldb = ldb_module_get_ctx(module); static const struct ridalloc_ridset_values o = { .alloc_pool = UINT64_MAX, .prev_pool = UINT64_MAX, .next_rid = UINT32_MAX, .used_pool = UINT32_MAX, }; struct ridalloc_ridset_values n = { .alloc_pool = 0, .prev_pool = 0, .next_rid = 0, .used_pool = 0, }; const char *no_attrs[] = { NULL }; struct ldb_result *res; /* steps: find the machine object for the DC construct the RID Set DN load rIDAvailablePool to find next available set modify RID Manager object to update rIDAvailablePool add the RID Set object link to the RID Set object in machine object */ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn); if (!server_dn) { talloc_free(tmp_ctx); return ldb_module_oom(module); } ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s", ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn); if (rid_set_dn == NULL) { talloc_free(tmp_ctx); return ldb_module_oom(module); } if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) { talloc_free(tmp_ctx); return ldb_module_oom(module); } /* grab a pool from the RID Manager object */ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* create the RID Set object */ msg = ldb_msg_new(tmp_ctx); msg->dn = rid_set_dn; ret = ldb_msg_add_string(msg, "objectClass", "rIDSet"); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = ridalloc_set_ridset_values(module, msg, &o, &n); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } /* we need this to go all the way to the top of the module * stack, as we need all the extra attributes added (including * complex ones like ntsecuritydescriptor). We must do this * as system, otherwise a user might end up owning the RID * set, and that would be bad... */ ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM | DSDB_MODIFY_RELAX, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* add the rIDSetReferences link */ msg = ldb_msg_new(tmp_ctx); msg->dn = machine_dn; /* we need the extended DN of the RID Set object for * rIDSetReferences */ ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs, DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } rid_set_dn = res->msgs[0]->dn; ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1)); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } msg->elements[0].flags = LDB_FLAG_MOD_ADD; ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s", ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } (*dn) = talloc_steal(mem_ctx, rid_set_dn); talloc_free(tmp_ctx); return LDB_SUCCESS; } /* create a RID Set object for this DC */ int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn, struct ldb_request *parent) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); struct ldb_dn *rid_manager_dn, *fsmo_role_dn; int ret; struct ldb_context *ldb = ldb_module_get_ctx(module); struct GUID fsmo_role_guid; const struct GUID *our_ntds_guid; NTSTATUS status; /* work out who is the RID Manager */ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } /* find the DN of the RID Manager */ ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s", ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID"); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return ldb_operr(ldb_module_get_ctx(module)); } our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module)); if (!our_ntds_guid) { talloc_free(tmp_ctx); return ldb_operr(ldb_module_get_ctx(module)); } if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) { ret = ridalloc_poke_rid_manager(module); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(ldb, "Request for remote creation of " "RID Set for this DC failed: %s", ldb_errstring(ldb)); } else { ldb_asprintf_errstring(ldb, "Remote RID Set creation needed"); } talloc_free(tmp_ctx); return LDB_ERR_UNWILLING_TO_PERFORM; } ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent); talloc_free(tmp_ctx); return ret; }