static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb) { const struct ldb_val *sidval; char *sidstring; struct dom_sid *sid; NTSTATUS status; /* We need the domain, so we get it from the objectSid that we hope is here... */ sidval = ldb_msg_find_ldb_val(local, "objectSid"); if (!sidval) return; /* Sorry, no SID today.. */ sid = talloc(remote_mp, struct dom_sid); if (sid == NULL) { return; } status = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NT_STATUS_IS_OK(status)) { talloc_free(sid); return; } if (!ldb_msg_find_ldb_val(local, "primaryGroupID")) return; /* Sorry, no SID today.. */ sid->num_auths--; sidstring = dom_sid_string(remote_mp, sid); talloc_free(sid); ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_attr_as_uint(local, "primaryGroupID", 0)); talloc_free(sidstring); }
static int handle_dereference(struct ldb_dn *dn, struct dsdb_openldap_dereference_result **dereference_attrs, const char *attr, const DATA_BLOB *val) { const struct ldb_val *entryUUIDblob, *sid_blob; struct ldb_message fake_msg; /* easier to use routines that expect an ldb_message */ int j; fake_msg.num_elements = 0; /* Look for this attribute in the returned control */ for (j = 0; dereference_attrs && dereference_attrs[j]; j++) { struct ldb_val source_dn = data_blob_string_const(dereference_attrs[j]->dereferenced_dn); if (ldb_attr_cmp(dereference_attrs[j]->source_attribute, attr) == 0 && data_blob_cmp(&source_dn, val) == 0) { fake_msg.num_elements = dereference_attrs[j]->num_attributes; fake_msg.elements = dereference_attrs[j]->attributes; break; } } if (!fake_msg.num_elements) { return LDB_SUCCESS; } /* Look for an OpenLDAP entryUUID */ entryUUIDblob = ldb_msg_find_ldb_val(&fake_msg, "entryUUID"); if (entryUUIDblob) { NTSTATUS status; enum ndr_err_code ndr_err; struct ldb_val guid_blob; struct GUID guid; status = GUID_from_data_blob(entryUUIDblob, &guid); if (!NT_STATUS_IS_OK(status)) { return LDB_ERR_INVALID_DN_SYNTAX; } ndr_err = ndr_push_struct_blob(&guid_blob, NULL, NULL, &guid, (ndr_push_flags_fn_t)ndr_push_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return LDB_ERR_INVALID_DN_SYNTAX; } ldb_dn_set_extended_component(dn, "GUID", &guid_blob); } sid_blob = ldb_msg_find_ldb_val(&fake_msg, "objectSID"); /* Look for the objectSID */ if (sid_blob) { ldb_dn_set_extended_component(dn, "SID", sid_blob); } return LDB_SUCCESS; }
uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg, const char *attr_name, uint64_t default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); char buf[sizeof("-9223372036854775808")]; char *end = NULL; uint64_t ret; if (!v || !v->data) { return default_value; } ZERO_STRUCT(buf); if (v->length >= sizeof(buf)) { return default_value; } memcpy(buf, v->data, v->length); errno = 0; ret = (uint64_t) strtoll(buf, &end, 10); if (errno != 0) { errno = 0; ret = (uint64_t) strtoull(buf, &end, 10); if (errno != 0) { return default_value; } } if (end && end[0] != '\0') { return default_value; } return ret; }
double ldb_msg_find_attr_as_double(const struct ldb_message *msg, const char *attr_name, double default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); char *buf; char *end = NULL; double ret; if (!v || !v->data) { return default_value; } buf = talloc_strndup(msg, (const char *)v->data, v->length); if (buf == NULL) { return default_value; } errno = 0; ret = strtod(buf, &end); talloc_free(buf); if (errno != 0) { return default_value; } if (end && end[0] != '\0') { return default_value; } return ret; }
int ldb_msg_find_attr_as_int(const struct ldb_message *msg, const char *attr_name, int default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); char buf[sizeof("-2147483648")]; char *end = NULL; int ret; if (!v || !v->data) { return default_value; } ZERO_STRUCT(buf); if (v->length >= sizeof(buf)) { return default_value; } memcpy(buf, v->data, v->length); errno = 0; ret = (int) strtoll(buf, &end, 10); if (errno != 0) { return default_value; } if (end && end[0] != '\0') { return default_value; } return ret; }
/* construct msDS-keyVersionNumber attr TODO: Make this based on the 'win2k' DS huristics bit... */ static int construct_msds_keyversionnumber(struct ldb_module *module, struct ldb_message *msg, enum ldb_scope scope, struct ldb_request *parent) { uint32_t i; enum ndr_err_code ndr_err; const struct ldb_val *omd_value; struct replPropertyMetaDataBlob *omd; int ret; omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData"); if (!omd_value) { /* We can't make up a key version number without meta data */ return LDB_SUCCESS; } if (!omd_value) { return LDB_SUCCESS; } omd = talloc(msg, struct replPropertyMetaDataBlob); if (!omd) { ldb_module_oom(module); return LDB_SUCCESS; } ndr_err = ndr_pull_struct_blob(omd_value, omd, omd, (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n", ldb_dn_get_linearized(msg->dn))); return ldb_operr(ldb_module_get_ctx(module)); } if (omd->version != 1) { DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n", omd->version, ldb_dn_get_linearized(msg->dn))); talloc_free(omd); return LDB_SUCCESS; } for (i=0; i<omd->ctr.ctr1.count; i++) { if (omd->ctr.ctr1.array[i].attid == DRSUAPI_ATTID_unicodePwd) { ret = samdb_msg_add_uint(ldb_module_get_ctx(module), msg, msg, "msDS-KeyVersionNumber", omd->ctr.ctr1.array[i].version); if (ret != LDB_SUCCESS) { talloc_free(omd); return ret; } break; } } return LDB_SUCCESS; }
static bool logon_hours_ok(struct ldb_message *msg, const char *name_for_logs) { /* In logon hours first bit is Sunday from 12AM to 1AM */ const struct ldb_val *hours; struct tm *utctime; time_t lasttime; const char *asct; uint8_t bitmask, bitpos; hours = ldb_msg_find_ldb_val(msg, "logonHours"); if (!hours) { DEBUG(5,("logon_hours_ok: No hours restrictions for user %s\n", name_for_logs)); return true; } if (hours->length != 168/8) { DEBUG(5,("logon_hours_ok: malformed logon hours restrictions for user %s\n", name_for_logs)); return true; } lasttime = time(NULL); utctime = gmtime(&lasttime); if (!utctime) { DEBUG(1, ("logon_hours_ok: failed to get gmtime. Failing logon for user %s\n", name_for_logs)); return false; } /* find the corresponding byte and bit */ bitpos = (utctime->tm_wday * 24 + utctime->tm_hour) % 168; bitmask = 1 << (bitpos % 8); if (! (hours->data[bitpos/8] & bitmask)) { struct tm *t = localtime(&lasttime); if (!t) { asct = "INVALID TIME"; } else { asct = asctime(t); if (!asct) { asct = "INVALID TIME"; } } DEBUG(1, ("logon_hours_ok: Account for user %s not allowed to " "logon at this time (%s).\n", name_for_logs, asct )); return false; } asct = asctime(utctime); DEBUG(5,("logon_hours_ok: user %s allowed to logon at this time (%s)\n", name_for_logs, asct ? asct : "UNKNOWN TIME" )); return true; }
const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, const char *attr_name, const char *default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); if (!v || !v->data) { return default_value; } if (v->data[v->length] != '\0') { return default_value; } return (const char *)v->data; }
static int inject_extended_dn_out(struct ldb_reply *ares, struct ldb_context *ldb, int type, bool remove_guid, bool remove_sid) { int ret; const DATA_BLOB *guid_blob; const DATA_BLOB *sid_blob; guid_blob = ldb_msg_find_ldb_val(ares->message, "objectGUID"); sid_blob = ldb_msg_find_ldb_val(ares->message, "objectSID"); if (!guid_blob) { ldb_set_errstring(ldb, "Did not find objectGUID to inject into extended DN"); return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_dn_set_extended_component(ares->message->dn, "GUID", guid_blob); if (ret != LDB_SUCCESS) { return ret; } if (sid_blob) { ret = ldb_dn_set_extended_component(ares->message->dn, "SID", sid_blob); if (ret != LDB_SUCCESS) { return ret; } } if (remove_guid) { ldb_msg_remove_attr(ares->message, "objectGUID"); } if (sid_blob && remove_sid) { ldb_msg_remove_attr(ares->message, "objectSID"); } return LDB_SUCCESS; }
/** * Reads schema_info structure from schemaInfo * attribute on SCHEMA partition * * @param dsdb_flags DSDB_FLAG_... flag of 0 */ int dsdb_module_schema_info_blob_read(struct ldb_module *ldb_module, uint32_t dsdb_flags, TALLOC_CTX *mem_ctx, struct ldb_val *schema_info_blob, struct ldb_request *parent) { int ldb_err; const struct ldb_val *blob_val; struct ldb_dn *schema_dn; struct ldb_result *schema_res = NULL; static const char *schema_attrs[] = { "schemaInfo", NULL }; schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ldb_module)); if (!schema_dn) { DEBUG(0,("dsdb_module_schema_info_blob_read: no schema dn present!\n")); return ldb_operr(ldb_module_get_ctx(ldb_module)); } ldb_err = dsdb_module_search(ldb_module, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, dsdb_flags, parent, NULL); if (ldb_err == LDB_ERR_NO_SUCH_OBJECT) { DEBUG(0,("dsdb_module_schema_info_blob_read: Schema DN not found!\n")); talloc_free(schema_res); return ldb_err; } else if (ldb_err != LDB_SUCCESS) { DEBUG(0,("dsdb_module_schema_info_blob_read: failed to find schemaInfo attribute\n")); talloc_free(schema_res); return ldb_err; } blob_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo"); if (!blob_val) { ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), "dsdb_module_schema_info_blob_read: no schemaInfo attribute found"); talloc_free(schema_res); return LDB_ERR_NO_SUCH_ATTRIBUTE; } /* transfer .data ownership to mem_ctx */ schema_info_blob->length = blob_val->length; schema_info_blob->data = talloc_steal(mem_ctx, blob_val->data); talloc_free(schema_res); return LDB_SUCCESS; }
WERROR dsdb_read_prefixes_from_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm) { WERROR werr; int ldb_ret; const struct ldb_val *prefix_val; struct smb_iconv_convenience *iconv_convenience; struct ldb_dn *schema_dn; struct ldb_result *schema_res = NULL; static const char *schema_attrs[] = { "prefixMap", NULL }; schema_dn = samdb_schema_dn(ldb); if (!schema_dn) { DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n")); return WERR_FOOBAR; } ldb_ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL); if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) { DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n")); talloc_free(schema_res); return WERR_FOOBAR; } else if (ldb_ret != LDB_SUCCESS) { DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n")); talloc_free(schema_res); return WERR_FOOBAR; } prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap"); if (!prefix_val) { DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n")); talloc_free(schema_res); return WERR_FOOBAR; } iconv_convenience = lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")); werr = _dsdb_prefixmap_from_ldb_val(prefix_val, iconv_convenience, mem_ctx, _pfm); talloc_free(schema_res); W_ERROR_NOT_OK_RETURN(werr); return WERR_OK; }
int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, const char *attr_name, int default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); if (!v || !v->data) { return default_value; } if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) { return 0; } if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) { return 1; } return default_value; }
struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg, const char *attr_name) { struct ldb_dn *res_dn; const struct ldb_val *v; v = ldb_msg_find_ldb_val(msg, attr_name); if (!v || !v->data) { return NULL; } res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v); if ( ! ldb_dn_validate(res_dn)) { talloc_free(res_dn); return NULL; } return res_dn; }
/** \details Build a PermanentEntryID structure \param emsabp_ctx pointer to the EMSABP context \param DisplayType the AB object display type \param msg pointer to the LDB message \param permEntryID pointer to the PermanentEntryID returned by the function \note This function only covers DT_CONTAINER AddressBook objects. It should be extended in the future to support more containers. \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_ENOUGH_RESOURCES or MAPI_E_CORRUPT_STORE */ _PUBLIC_ enum MAPISTATUS emsabp_set_PermanentEntryID(struct emsabp_context *emsabp_ctx, uint32_t DisplayType, struct ldb_message *msg, struct PermanentEntryID *permEntryID) { struct GUID *guid = (struct GUID *) NULL; const struct ldb_val *ldb_value = NULL; const char *dn_str; /* Sanity checks */ OPENCHANGE_RETVAL_IF(!permEntryID, MAPI_E_NOT_ENOUGH_RESOURCES, NULL); permEntryID->ID_type = 0x0; permEntryID->R1 = 0x0; permEntryID->R2 = 0x0; permEntryID->R3 = 0x0; memcpy(permEntryID->ProviderUID.ab, GUID_NSPI, 16); permEntryID->R4 = 0x1; permEntryID->DisplayType = DisplayType; permEntryID->dn = NULL; if (!msg) { permEntryID->dn = talloc_strdup(emsabp_ctx->mem_ctx, "/"); OPENCHANGE_RETVAL_IF(!permEntryID->dn, MAPI_E_NOT_ENOUGH_MEMORY, NULL); } else if (DisplayType == DT_CONTAINER) { ldb_value = ldb_msg_find_ldb_val(msg, "objectGUID"); OPENCHANGE_RETVAL_IF(!ldb_value, MAPI_E_CORRUPT_STORE, NULL); guid = talloc_zero(emsabp_ctx->mem_ctx, struct GUID); GUID_from_data_blob(ldb_value, guid); permEntryID->dn = talloc_asprintf(emsabp_ctx->mem_ctx, EMSABP_DN, guid->time_low, guid->time_mid, guid->time_hi_and_version, guid->clock_seq[0], guid->clock_seq[1], guid->node[0], guid->node[1], guid->node[2], guid->node[3], guid->node[4], guid->node[5]); OPENCHANGE_RETVAL_IF(!permEntryID->dn, MAPI_E_NOT_ENOUGH_RESOURCES, guid); talloc_free(guid); } else {
bool ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *ctx, LDAPMessage *res, const char *field, struct security_descriptor **sd) { const struct ldb_val *val; enum ndr_err_code ndr_err; val = ldb_msg_find_ldb_val(res->msgs[0], field); *sd = talloc(ctx, struct security_descriptor); if (*sd == NULL) { return -1; } /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */ ndr_err = ndr_pull_struct_blob(val, *sd, NULL, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(*sd); return -1; } return 0; }
static WERROR get_repl_prop_metadata_ctr(TALLOC_CTX *mem_ctx, struct ldb_context *samdb, struct ldb_dn *dn, struct replPropertyMetaDataBlob *obj_metadata_ctr) { int ret; struct ldb_result *res; const char *attrs[] = { "replPropertyMetaData", NULL }; const struct ldb_val *omd_value; enum ndr_err_code ndr_err; ret = ldb_search(samdb, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL); if (ret != LDB_SUCCESS || res->count != 1) { DEBUG(0, (__location__ ": Failed search for replPropertyMetaData attribute on %s", ldb_dn_get_linearized(dn))); return WERR_INTERNAL_ERROR; } omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData"); if (!omd_value) { DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n", ldb_dn_get_linearized(dn))); talloc_free(res); return WERR_INTERNAL_ERROR; } ndr_err = ndr_pull_struct_blob(omd_value, mem_ctx, obj_metadata_ctr, (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n", ldb_dn_get_linearized(dn))); talloc_free(res); return WERR_INTERNAL_ERROR; } talloc_free(res); return WERR_OK; }
/** * Fill in credentials for the machine trust account, from the secrets database. * * @param cred Credentials structure to fill in * @retval NTSTATUS error detailing any failure */ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, const char *base, const char *filter) { TALLOC_CTX *mem_ctx; struct ldb_context *ldb; int ldb_ret; struct ldb_message **msgs; const char *attrs[] = { "secret", "priorSecret", "samAccountName", "flatname", "realm", "secureChannelType", "ntPwdHash", "msDS-KeyVersionNumber", "saltPrincipal", "privateKeytab", "krb5Keytab", NULL }; const char *machine_account; const char *password; const char *old_password; const char *domain; const char *realm; enum netr_SchannelType sct; const char *salt_principal; const char *keytab; /* ok, we are going to get it now, don't recurse back here */ cred->machine_account_pending = False; /* some other parts of the system will key off this */ cred->machine_account = True; mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password"); /* Local secrets are stored in secrets.ldb */ ldb = secrets_db_connect(mem_ctx); if (!ldb) { /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); DEBUG(1, ("Could not open secrets.ldb\n")); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } /* search for the secret record */ ldb_ret = gendb_search(ldb, mem_ctx, ldb_dn_new(mem_ctx, ldb, base), &msgs, attrs, "%s", filter); if (ldb_ret == 0) { DEBUG(1, ("Could not find entry to match filter: %s\n", filter)); /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } else if (ldb_ret != 1) { DEBUG(1, ("Found more than one (%d) entry to match filter: %s\n", ldb_ret, filter)); /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } password = ldb_msg_find_attr_as_string(msgs[0], "secret", NULL); old_password = ldb_msg_find_attr_as_string(msgs[0], "priorSecret", NULL); machine_account = ldb_msg_find_attr_as_string(msgs[0], "samAccountName", NULL); if (!machine_account) { DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", cli_credentials_get_domain(cred))); /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } salt_principal = ldb_msg_find_attr_as_string(msgs[0], "saltPrincipal", NULL); cli_credentials_set_salt_principal(cred, salt_principal); sct = ldb_msg_find_attr_as_int(msgs[0], "secureChannelType", 0); if (sct) { cli_credentials_set_secure_channel_type(cred, sct); } if (!password) { const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash"); struct samr_Password hash; ZERO_STRUCT(hash); if (nt_password_hash) { memcpy(hash.hash, nt_password_hash->data, MIN(nt_password_hash->length, sizeof(hash.hash))); cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED); } else { cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } } else { cli_credentials_set_password(cred, password, CRED_SPECIFIED); } domain = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL); if (domain) { cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); } realm = ldb_msg_find_attr_as_string(msgs[0], "realm", NULL); if (realm) { cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); } cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msgs[0], "msDS-KeyVersionNumber", 0)); /* If there was an external keytab specified by reference in * the LDB, then use this. Otherwise we will make one up * (chewing CPU time) from the password */ keytab = ldb_msg_find_attr_as_string(msgs[0], "krb5Keytab", NULL); if (keytab) { cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED); } else { keytab = ldb_msg_find_attr_as_string(msgs[0], "privateKeytab", NULL); if (keytab) { keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, keytab)); if (keytab) { cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED); } } } talloc_free(mem_ctx); return NT_STATUS_OK; }
WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df) { 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, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm"))); schema->fsmo.we_are_master = true; schema->fsmo.master_dn = ldb_dn_new_fmt(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); msg = ldb_msg_canonicalize(ldb, ldif->msg); if (!msg) { goto nomem; } talloc_steal(mem_ctx, msg); 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) { info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000"); if (!info_val_default.data) { goto nomem; } info_val = &info_val_default; } status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val); if (!W_ERROR_IS_OK(status)) { goto failed; } /* * load the attribute and class definitions outof df */ while ((ldif = ldb_ldif_read_string(ldb, &df))) { talloc_steal(mem_ctx, ldif); msg = ldb_msg_canonicalize(ldb, ldif->msg); if (!msg) { 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; }
/** * Retrieve the domain SID from the secrets database. * @return pointer to a SID object if the SID could be obtained, NULL otherwise */ struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, const char *domain, enum netr_SchannelType *sec_channel_type, char **errstring) { struct ldb_context *ldb; struct ldb_message *msg; int ldb_ret; const char *attrs[] = { "objectSid", "secureChannelType", NULL }; struct dom_sid *result = NULL; const struct ldb_val *v; enum ndr_err_code ndr_err; *errstring = NULL; ldb = secrets_db_connect(mem_ctx, lp_ctx); if (ldb == NULL) { DEBUG(5, ("secrets_db_connect failed\n")); return NULL; } ldb_ret = dsdb_search_one(ldb, ldb, &msg, ldb_dn_new(mem_ctx, ldb, SECRETS_PRIMARY_DOMAIN_DN), LDB_SCOPE_ONELEVEL, attrs, 0, SECRETS_PRIMARY_DOMAIN_FILTER, domain); if (ldb_ret != LDB_SUCCESS) { *errstring = talloc_asprintf(mem_ctx, "Failed to find record for %s in %s: %s: %s", domain, (char *) ldb_get_opaque(ldb, "ldb_url"), ldb_strerror(ldb_ret), ldb_errstring(ldb)); return NULL; } v = ldb_msg_find_ldb_val(msg, "objectSid"); if (v == NULL) { *errstring = talloc_asprintf(mem_ctx, "Failed to find a SID on record for %s in %s", domain, (char *) ldb_get_opaque(ldb, "ldb_url")); return NULL; } if (sec_channel_type) { int t; t = ldb_msg_find_attr_as_int(msg, "secureChannelType", -1); if (t == -1) { *errstring = talloc_asprintf(mem_ctx, "Failed to find secureChannelType for %s in %s", domain, (char *) ldb_get_opaque(ldb, "ldb_url")); return NULL; } *sec_channel_type = t; } result = talloc(mem_ctx, struct dom_sid); if (result == NULL) { talloc_free(ldb); return NULL; } ndr_err = ndr_pull_struct_blob(v, result, result, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { *errstring = talloc_asprintf(mem_ctx, "Failed to parse SID on record for %s in %s", domain, (char *) ldb_get_opaque(ldb, "ldb_url")); talloc_free(result); talloc_free(ldb); return NULL; } return result; }
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; }
static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char **name, uint32_t *type, DATA_BLOB *data) { const struct ldb_val *val; uint32_t value_type; if (name != NULL) { *name = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "value", "")); } value_type = ldb_msg_find_attr_as_uint(msg, "type", 0); *type = value_type; val = ldb_msg_find_ldb_val(msg, "data"); switch (value_type) { case REG_SZ: case REG_EXPAND_SZ: if (val != NULL) { /* The data should be provided as UTF16 string */ convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data, &data->length); } else { data->data = NULL; data->length = 0; } break; case REG_DWORD: case REG_DWORD_BIG_ENDIAN: if (val != NULL) { /* The data is a plain DWORD */ uint32_t tmp = strtoul((char *)val->data, NULL, 0); data->data = talloc_size(mem_ctx, sizeof(uint32_t)); if (data->data != NULL) { SIVAL(data->data, 0, tmp); } data->length = sizeof(uint32_t); } else { data->data = NULL; data->length = 0; } break; case REG_QWORD: if (val != NULL) { /* The data is a plain QWORD */ uint64_t tmp = strtoull((char *)val->data, NULL, 0); data->data = talloc_size(mem_ctx, sizeof(uint64_t)); if (data->data != NULL) { SBVAL(data->data, 0, tmp); } data->length = sizeof(uint64_t); } else { data->data = NULL; data->length = 0; } break; case REG_BINARY: default: if (val != NULL) { data->data = talloc_memdup(mem_ctx, val->data, val->length); data->length = val->length; } else { data->data = NULL; data->length = 0; } break; } }
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_result *schema_res, struct ldb_result *attrs_class_res, struct dsdb_schema **schema_out, char **error_string) { WERROR status; const struct ldb_val *prefix_val; const struct ldb_val *info_val; struct ldb_val info_val_default; struct dsdb_schema *schema; struct loadparm_context *lp_ctx = NULL; int ret; schema = dsdb_new_schema(mem_ctx); if (!schema) { dsdb_oom(error_string, mem_ctx); return ldb_operr(ldb); } schema->base_dn = talloc_steal(schema, schema_res->msgs[0]->dn); prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap"); if (!prefix_val) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: no prefixMap attribute found"); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo"); if (!info_val) { status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s", win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return ldb_operr(ldb); } info_val = &info_val_default; } status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: failed to load oid mappings: %s", win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } ret = dsdb_load_ldb_results_into_schema(mem_ctx, ldb, schema, attrs_class_res, error_string); if (ret != LDB_SUCCESS) { return ret; } schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner"); if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) { schema->fsmo.we_are_master = true; } else { schema->fsmo.we_are_master = false; } lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), struct loadparm_context); if (lp_ctx) { bool allowed = lpcfg_parm_bool(lp_ctx, NULL, "dsdb", "schema update allowed", false); schema->fsmo.update_allowed = allowed; } else { schema->fsmo.update_allowed = false; } DEBUG(5, ("schema_fsmo_init: we are master[%s] updates allowed[%s]\n", (schema->fsmo.we_are_master?"yes":"no"), (schema->fsmo.update_allowed?"yes":"no"))); *schema_out = schema; return LDB_SUCCESS; }
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_result *schema_res, struct ldb_result *attrs_res, struct ldb_result *objectclass_res, struct dsdb_schema **schema_out, char **error_string) { WERROR status; unsigned int i; const struct ldb_val *prefix_val; const struct ldb_val *info_val; struct ldb_val info_val_default; struct dsdb_schema *schema; schema = dsdb_new_schema(mem_ctx); if (!schema) { dsdb_oom(error_string, mem_ctx); return ldb_operr(ldb); } schema->base_dn = talloc_steal(schema, schema_res->msgs[0]->dn); prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap"); if (!prefix_val) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: no prefixMap attribute found"); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo"); if (!info_val) { status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s", win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return ldb_operr(ldb); } info_val = &info_val_default; } status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: failed to load oid mappings: %s", win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } for (i=0; i < attrs_res->count; i++) { status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i]); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: failed to load attribute definition: %s:%s", ldb_dn_get_linearized(attrs_res->msgs[i]->dn), win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } } for (i=0; i < objectclass_res->count; i++) { status = dsdb_class_from_ldb(schema, objectclass_res->msgs[i]); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: failed to load class definition: %s:%s", ldb_dn_get_linearized(objectclass_res->msgs[i]->dn), win_errstr(status)); DEBUG(0,(__location__ ": %s\n", *error_string)); return LDB_ERR_CONSTRAINT_VIOLATION; } } schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner"); if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) { schema->fsmo.we_are_master = true; } else { schema->fsmo.we_are_master = false; } DEBUG(5, ("schema_fsmo_init: we are master: %s\n", (schema->fsmo.we_are_master?"yes":"no"))); *schema_out = schema; return LDB_SUCCESS; }
/* read back a credentials back for a computer */ NTSTATUS schannel_fetch_session_key_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *computer_name, struct netlogon_creds_CredentialState **creds) { struct ldb_result *res; int ret; const struct ldb_val *val; *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); if (!*creds) { return NT_STATUS_NO_MEMORY; } ret = ldb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "(computerName=%s)", computer_name); if (ret != LDB_SUCCESS) { DEBUG(3,("schannel: Failed to find a record for client %s: %s\n", computer_name, ldb_errstring(ldb))); return NT_STATUS_INVALID_HANDLE; } if (res->count != 1) { DEBUG(3,("schannel: Failed to find a record for client: %s (found %d records)\n", computer_name, res->count)); talloc_free(res); return NT_STATUS_INVALID_HANDLE; } val = ldb_msg_find_ldb_val(res->msgs[0], "sessionKey"); if (val == NULL || val->length != 16) { DEBUG(1,("schannel: record in schannel DB must contain a sessionKey of length 16, when searching for client: %s\n", computer_name)); talloc_free(res); return NT_STATUS_INTERNAL_ERROR; } memcpy((*creds)->session_key, val->data, 16); val = ldb_msg_find_ldb_val(res->msgs[0], "seed"); if (val == NULL || val->length != 8) { DEBUG(1,("schannel: record in schannel DB must contain a vaid seed of length 8, when searching for client: %s\n", computer_name)); talloc_free(res); return NT_STATUS_INTERNAL_ERROR; } memcpy((*creds)->seed.data, val->data, 8); val = ldb_msg_find_ldb_val(res->msgs[0], "clientState"); if (val == NULL || val->length != 8) { DEBUG(1,("schannel: record in schannel DB must contain a vaid clientState of length 8, when searching for client: %s\n", computer_name)); talloc_free(res); return NT_STATUS_INTERNAL_ERROR; } memcpy((*creds)->client.data, val->data, 8); val = ldb_msg_find_ldb_val(res->msgs[0], "serverState"); if (val == NULL || val->length != 8) { DEBUG(1,("schannel: record in schannel DB must contain a vaid serverState of length 8, when searching for client: %s\n", computer_name)); talloc_free(res); return NT_STATUS_INTERNAL_ERROR; } memcpy((*creds)->server.data, val->data, 8); (*creds)->negotiate_flags = ldb_msg_find_attr_as_int(res->msgs[0], "negotiateFlags", 0); (*creds)->secure_channel_type = ldb_msg_find_attr_as_int(res->msgs[0], "secureChannelType", 0); (*creds)->account_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "accountName", NULL)); if ((*creds)->account_name == NULL) { talloc_free(res); return NT_STATUS_NO_MEMORY; } (*creds)->computer_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "computerName", NULL)); if ((*creds)->computer_name == NULL) { talloc_free(res); return NT_STATUS_NO_MEMORY; } val = ldb_msg_find_ldb_val(res->msgs[0], "objectSid"); if (val) { (*creds)->sid = schannel_ldb_val_dom_sid(*creds, val); if ((*creds)->sid == NULL) { talloc_free(res); return NT_STATUS_INTERNAL_ERROR; } } else { (*creds)->sid = NULL; } talloc_free(res); return NT_STATUS_OK; }
/** * Fill in credentials for the machine trust account, from the secrets database. * * @param cred Credentials structure to fill in * @retval NTSTATUS error detailing any failure */ static NTSTATUS cli_credentials_set_secrets_lct(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct ldb_context *ldb, const char *base, const char *filter, time_t secrets_tdb_last_change_time, const char *secrets_tdb_password, char **error_string) { TALLOC_CTX *mem_ctx; int ldb_ret; struct ldb_message *msg; const char *machine_account; const char *password; const char *domain; const char *realm; enum netr_SchannelType sct; const char *salt_principal; char *keytab; const struct ldb_val *whenChanged; time_t lct; /* ok, we are going to get it now, don't recurse back here */ cred->machine_account_pending = false; /* some other parts of the system will key off this */ cred->machine_account = true; mem_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb"); if (!ldb) { /* Local secrets are stored in secrets.ldb */ ldb = secrets_db_connect(mem_ctx, lp_ctx); if (!ldb) { *error_string = talloc_strdup(cred, "Could not open secrets.ldb"); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } } ldb_ret = dsdb_search_one(ldb, mem_ctx, &msg, ldb_dn_new(mem_ctx, ldb, base), LDB_SCOPE_SUBTREE, NULL, 0, "%s", filter); if (ldb_ret != LDB_SUCCESS) { *error_string = talloc_asprintf(cred, "Could not find entry to match filter: '%s' base: '%s': %s: %s", filter, base ? base : "", ldb_strerror(ldb_ret), ldb_errstring(ldb)); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } password = ldb_msg_find_attr_as_string(msg, "secret", NULL); whenChanged = ldb_msg_find_ldb_val(msg, "whenChanged"); if (!whenChanged || ldb_val_to_time(whenChanged, &lct) != LDB_SUCCESS) { /* This attribute is mandetory */ talloc_free(mem_ctx); return NT_STATUS_NOT_FOUND; } /* Don't set secrets.ldb info if the secrets.tdb entry was more recent */ if (lct < secrets_tdb_last_change_time) { talloc_free(mem_ctx); return NT_STATUS_NOT_FOUND; } if (lct == secrets_tdb_last_change_time && secrets_tdb_password && strcmp(password, secrets_tdb_password) != 0) { talloc_free(mem_ctx); return NT_STATUS_NOT_FOUND; } cli_credentials_set_password_last_changed_time(cred, lct); machine_account = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); if (!machine_account) { machine_account = ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL); if (!machine_account) { const char *ldap_bind_dn = ldb_msg_find_attr_as_string(msg, "ldapBindDn", NULL); if (!ldap_bind_dn) { *error_string = talloc_asprintf(cred, "Could not find 'samAccountName', " "'servicePrincipalName' or " "'ldapBindDn' in secrets record: %s", ldb_dn_get_linearized(msg->dn)); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } else { /* store bind dn in credentials */ cli_credentials_set_bind_dn(cred, ldap_bind_dn); } } } salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL); cli_credentials_set_salt_principal(cred, salt_principal); sct = ldb_msg_find_attr_as_int(msg, "secureChannelType", 0); if (sct) { cli_credentials_set_secure_channel_type(cred, sct); } if (!password) { const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msg, "unicodePwd"); struct samr_Password hash; ZERO_STRUCT(hash); if (nt_password_hash) { memcpy(hash.hash, nt_password_hash->data, MIN(nt_password_hash->length, sizeof(hash.hash))); cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED); } else { cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } } else { cli_credentials_set_password(cred, password, CRED_SPECIFIED); } domain = ldb_msg_find_attr_as_string(msg, "flatname", NULL); if (domain) { cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); } realm = ldb_msg_find_attr_as_string(msg, "realm", NULL); if (realm) { cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); } if (machine_account) { cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); } cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0)); /* If there was an external keytab specified by reference in * the LDB, then use this. Otherwise we will make one up * (chewing CPU time) from the password */ keytab = keytab_name_from_msg(cred, ldb, msg); if (keytab) { cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED); talloc_free(keytab); } talloc_free(mem_ctx); return NT_STATUS_OK; }
/* construct the parent GUID for an entry from a message */ static int construct_parent_guid(struct ldb_module *module, struct ldb_message *msg, enum ldb_scope scope, struct ldb_request *parent) { struct ldb_result *res, *parent_res; const struct ldb_val *parent_guid; const char *attrs[] = { "instanceType", NULL }; const char *attrs2[] = { "objectGUID", NULL }; uint32_t instanceType; int ret; struct ldb_dn *parent_dn; struct ldb_val v; /* determine if the object is NC by instance type */ ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs, DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_RECYCLED, parent); if (ret != LDB_SUCCESS) { return ret; } instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], "instanceType", 0); talloc_free(res); if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) { DEBUG(4,(__location__ ": Object %s is NC\n", ldb_dn_get_linearized(msg->dn))); return LDB_SUCCESS; } parent_dn = ldb_dn_get_parent(msg, msg->dn); if (parent_dn == NULL) { DEBUG(4,(__location__ ": Failed to find parent for dn %s\n", ldb_dn_get_linearized(msg->dn))); return LDB_SUCCESS; } ret = dsdb_module_search_dn(module, msg, &parent_res, parent_dn, attrs2, DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_RECYCLED, parent); talloc_free(parent_dn); /* not NC, so the object should have a parent*/ if (ret == LDB_ERR_NO_SUCH_OBJECT) { return ldb_error(ldb_module_get_ctx(module), LDB_ERR_OPERATIONS_ERROR, talloc_asprintf(msg, "Parent dn for %s does not exist", ldb_dn_get_linearized(msg->dn))); } else if (ret != LDB_SUCCESS) { return ret; } parent_guid = ldb_msg_find_ldb_val(parent_res->msgs[0], "objectGUID"); if (!parent_guid) { talloc_free(parent_res); return LDB_SUCCESS; } v = data_blob_dup_talloc(parent_res, *parent_guid); if (!v.data) { talloc_free(parent_res); return ldb_oom(ldb_module_get_ctx(module)); } ret = ldb_msg_add_steal_value(msg, "parentGUID", &v); talloc_free(parent_res); return ret; }