/* convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob */ static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { struct security_descriptor *sd; enum ndr_err_code ndr_err; sd = talloc(mem_ctx, struct security_descriptor); if (sd == NULL) { return -1; } ndr_err = ndr_pull_struct_blob(in, sd, sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { /* If this does not parse, then it is probably SDDL, and we should try it that way */ const struct dom_sid *sid = samdb_domain_sid(ldb); talloc_free(sd); sd = sddl_decode(mem_ctx, (const char *)in->data, sid); if (sd == NULL) { return -1; } } ndr_err = ndr_push_struct_blob(out, mem_ctx, sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor); talloc_free(sd); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return -1; } return 0; }
static DATA_BLOB *get_new_descriptor(struct ldb_module *module, struct ldb_dn *dn, TALLOC_CTX *mem_ctx, const struct dsdb_class *objectclass, const struct ldb_val *parent, const struct ldb_val *object, const struct ldb_val *old_sd, uint32_t sd_flags) { struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL; struct security_descriptor *old_descriptor = NULL; struct security_descriptor *new_sd, *final_sd; DATA_BLOB *linear_sd; enum ndr_err_code ndr_err; struct ldb_context *ldb = ldb_module_get_ctx(module); struct auth_session_info *session_info = ldb_get_opaque(ldb, "sessionInfo"); const struct dom_sid *domain_sid = samdb_domain_sid(ldb); char *sddl_sd; struct dom_sid *default_owner; struct dom_sid *default_group; struct security_descriptor *default_descriptor = NULL; struct GUID *object_list = NULL; if (objectclass != NULL) { default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); object_list = talloc_zero_array(mem_ctx, struct GUID, 2); if (object_list == NULL) { return NULL; } object_list[0] = objectclass->schemaIDGUID; }
static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args) { PyObject *py_ldb; struct ldb_context *ldb; const struct dom_sid *sid; PyObject *ret; char *retstr; if (!PyArg_ParseTuple(args, "O", &py_ldb)) return NULL; PyErr_LDB_OR_RAISE(py_ldb, ldb); sid = samdb_domain_sid(ldb); if (!sid) { PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed"); return NULL; } retstr = dom_sid_string(NULL, sid); if (retstr == NULL) { PyErr_NoMemory(); return NULL; } ret = PyString_FromString(retstr); talloc_free(retstr); return ret; }
static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct security_token *token, struct ldb_context *ldb) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); const struct dom_sid *domain_sid = samdb_domain_sid(ldb); struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS); struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS); struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS); struct dom_sid *dag_sid; struct ldb_dn *nc_root; int ret; ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return NULL; } if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) { if (security_token_has_sid(token, sa_sid)) { dag_sid = dom_sid_dup(mem_ctx, sa_sid); } else if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, sa_sid); } else { dag_sid = NULL; } } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) { if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else { dag_sid = NULL; } } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) { if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else { dag_sid = NULL; } } else { dag_sid = NULL; } talloc_free(tmp_ctx); return dag_sid; }
static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx, const struct dsdb_class *objectclass) { struct ldb_context *ldb = ldb_module_get_ctx(module); struct security_descriptor *sd; const struct dom_sid *domain_sid = samdb_domain_sid(ldb); if (!objectclass->defaultSecurityDescriptor || !domain_sid) { return NULL; } sd = sddl_decode(mem_ctx, objectclass->defaultSecurityDescriptor, domain_sid); return sd; }
/* convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format) */ static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) { struct security_descriptor *sd; const struct dom_sid *sid = samdb_domain_sid(ldb); sd = sddl_decode(mem_ctx, (const char *)in->data, sid); out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, (ndr_print_fn_t)ndr_print_security_descriptor, "SDDL", sd); out->length = strlen((const char *)out->data); talloc_free(sd); return 0; } return ldb_handler_copy(ldb, mem_ctx, in, out); }
static DATA_BLOB *get_new_descriptor(struct ldb_module *module, struct ldb_dn *dn, TALLOC_CTX *mem_ctx, const struct dsdb_class *objectclass, const struct ldb_val *parent, const struct ldb_val *object, const struct ldb_val *old_sd, uint32_t sd_flags) { struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL; struct security_descriptor *old_descriptor = NULL; struct security_descriptor *new_sd, *final_sd; DATA_BLOB *linear_sd; enum ndr_err_code ndr_err; struct ldb_context *ldb = ldb_module_get_ctx(module); struct auth_session_info *session_info = ldb_get_opaque(ldb, "sessionInfo"); const struct dom_sid *domain_sid = samdb_domain_sid(ldb); char *sddl_sd; struct dom_sid *default_owner; struct dom_sid *default_group; if (object) { user_descriptor = talloc(mem_ctx, struct security_descriptor); if (!user_descriptor) { return NULL; } ndr_err = ndr_pull_struct_blob(object, user_descriptor, user_descriptor, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(user_descriptor); return NULL; } } else {
/* drsuapi_DsBind */ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsBind *r) { struct drsuapi_bind_state *b_state; struct dcesrv_handle *handle; struct drsuapi_DsBindInfoCtr *bind_info; struct GUID site_guid; struct ldb_result *site_res; struct ldb_dn *server_site_dn; static const char *site_attrs[] = { "objectGUID", NULL }; struct ldb_result *ntds_res; struct ldb_dn *ntds_dn; static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL }; uint32_t pid; uint32_t repl_epoch; int ret; struct auth_session_info *auth_info; WERROR werr; bool connected_as_system = false; r->out.bind_info = NULL; ZERO_STRUCTP(r->out.bind_handle); b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state); W_ERROR_HAVE_NO_MEMORY(b_state); /* if this is a DC connecting, give them system level access */ werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL); if (W_ERROR_IS_OK(werr)) { DEBUG(3,(__location__ ": doing DsBind with system_session\n")); auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx); connected_as_system = true; } else { auth_info = dce_call->conn->auth_state.session_info; } /* * connect to the samdb */ b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, auth_info, 0); if (!b_state->sam_ctx) { return WERR_FOOBAR; } if (connected_as_system) { b_state->sam_ctx_system = b_state->sam_ctx; } else { /* an RODC also needs system samdb access for secret attribute replication */ werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER, samdb_domain_sid(b_state->sam_ctx)); if (W_ERROR_IS_OK(werr)) { b_state->sam_ctx_system = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0); if (!b_state->sam_ctx_system) { return WERR_FOOBAR; } } } /* * find out the guid of our own site */ server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx); W_ERROR_HAVE_NO_MEMORY(server_site_dn); ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res, server_site_dn, LDB_SCOPE_BASE, site_attrs, "(objectClass=*)"); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } if (site_res->count != 1) { return WERR_DS_DRA_INTERNAL_ERROR; } site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID"); /* * lookup the local servers Replication Epoch */ ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx, mem_ctx); W_ERROR_HAVE_NO_MEMORY(ntds_dn); ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res, ntds_dn, LDB_SCOPE_BASE, ntds_attrs, "(objectClass=*)"); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } if (ntds_res->count != 1) { return WERR_DS_DRA_INTERNAL_ERROR; } repl_epoch = ldb_msg_find_attr_as_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0); /* * The "process identifier" of the client. * According to the WSPP docs, sectin 5.35, this is * for informational and debugging purposes only. * The assignment is implementation specific. */ pid = 0; /* * store the clients bind_guid */ if (r->in.bind_guid) { b_state->remote_bind_guid = *r->in.bind_guid; } /* * store the clients bind_info */ if (r->in.bind_info) { switch (r->in.bind_info->length) { case 24: { struct drsuapi_DsBindInfo24 *info24; info24 = &r->in.bind_info->info.info24; b_state->remote_info28.supported_extensions = info24->supported_extensions; b_state->remote_info28.site_guid = info24->site_guid; b_state->remote_info28.pid = info24->pid; b_state->remote_info28.repl_epoch = 0; break; } case 28: b_state->remote_info28 = r->in.bind_info->info.info28; break; } } /* * fill in our local bind info 28 */ b_state->local_info28.supported_extensions = 0; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; #if 0 /* we don't support MSZIP compression (only decompression) */ b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; #endif b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; #if 0 /* we don't support XPRESS compression yet */ b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; #endif b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10; b_state->local_info28.site_guid = site_guid; b_state->local_info28.pid = pid; b_state->local_info28.repl_epoch = repl_epoch; /* * allocate the return bind_info */ bind_info = talloc_zero(mem_ctx, struct drsuapi_DsBindInfoCtr); W_ERROR_HAVE_NO_MEMORY(bind_info); bind_info->length = 28; bind_info->info.info28 = b_state->local_info28; /* * allocate a bind handle */ handle = dcesrv_handle_new(dce_call->context, DRSUAPI_BIND_HANDLE); W_ERROR_HAVE_NO_MEMORY(handle); handle->data = talloc_steal(handle, b_state); /* * prepare reply */ r->out.bind_info = bind_info; *r->out.bind_handle = handle->wire_handle; return WERR_OK; }