static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { struct dom_sid sid; enum ndr_err_code ndr_err; if (ldif_comparision_objectSid_isString(in)) { if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) { return 0; } } /* Perhaps not a string after all */ *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1); if (!out->data) { return -1; } (*out).length = strhex_to_str((char *)out->data, out->length, (const char *)in->data, in->length); /* Check it looks like a SID */ ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return -1; } return 0; }
static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, const TDB_DATA dbuf) { struct share_mode_data *d; enum ndr_err_code ndr_err; uint32_t i; DATA_BLOB blob; d = talloc(mem_ctx, struct share_mode_data); if (d == NULL) { DEBUG(0, ("talloc failed\n")); goto fail; } blob.data = dbuf.dptr; blob.length = dbuf.dsize; ndr_err = ndr_pull_struct_blob_all( &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n", ndr_errstr(ndr_err))); goto fail; } /* * Initialize the values that are [skip] in the idl. The NDR code does * not initialize them. */ for (i=0; i<d->num_share_modes; i++) { struct share_mode_entry *e = &d->share_modes[i]; e->stale = false; e->lease = NULL; if (e->op_type != LEASE_OPLOCK) { continue; } if (e->lease_idx >= d->num_leases) { continue; } e->lease = &d->leases[e->lease_idx]; } d->modified = false; d->fresh = false; if (DEBUGLEVEL >= 10) { DEBUG(10, ("parse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } return d; fail: TALLOC_FREE(d); return NULL; }
static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct drsuapi_DsReplicaAttribute *in, TALLOC_CTX *mem_ctx, struct ldb_message_element *out) { uint32_t i; out->flags = 0; out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName); W_ERROR_HAVE_NO_MEMORY(out->name); out->num_values = in->value_ctr.num_values; out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values); W_ERROR_HAVE_NO_MEMORY(out->values); for (i=0; i < out->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3Binary id3b; char *binary; char *str; enum ndr_err_code ndr_err; if (in->value_ctr.values[i].blob == NULL) { return WERR_FOOBAR; } if (in->value_ctr.values[i].blob->length == 0) { return WERR_FOOBAR; } ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob, out->values, schema->iconv_convenience, &id3b, (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); return ntstatus_to_werror(status); } /* TODO: handle id3.guid and id3.sid */ binary = data_blob_hex_string(out->values, &id3b.binary); W_ERROR_HAVE_NO_MEMORY(binary); str = talloc_asprintf(out->values, "B:%u:%s:%s", (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */ binary, id3b.dn); W_ERROR_HAVE_NO_MEMORY(str); /* TODO: handle id3.guid and id3.sid */ out->values[i] = data_blob_string_const(str); } return WERR_OK; }
/** build a GUID from a NDR data blob */ _PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid) { enum ndr_err_code ndr_err; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(NULL); NT_STATUS_HAVE_NO_MEMORY(mem_ctx); ndr_err = ndr_pull_struct_blob_all(b, mem_ctx, NULL, guid, (ndr_pull_flags_fn_t)ndr_pull_GUID); talloc_free(mem_ctx); return ndr_map_error2ntstatus(ndr_err); }
/* winreg_CreateKey */ static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_CreateKey *r) { struct dcesrv_handle *h, *newh; struct security_descriptor sd; struct registry_key *key; WERROR result; DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY); key = h->data; newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY); switch (security_session_user_level(dce_call->conn->auth_state.session_info)) { case SECURITY_SYSTEM: case SECURITY_ADMINISTRATOR: /* the security descriptor is optional */ if (r->in.secdesc != NULL) { DATA_BLOB sdblob; enum ndr_err_code ndr_err; sdblob.data = r->in.secdesc->sd.data; sdblob.length = r->in.secdesc->sd.len; if (sdblob.data == NULL) { return WERR_INVALID_PARAM; } ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_INVALID_PARAM; } } result = reg_key_add_name(newh, key, r->in.name.name, NULL, r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data); if (W_ERROR_IS_OK(result)) { r->out.new_handle = &newh->wire_handle; } else { talloc_free(newh); } return result; default: return WERR_ACCESS_DENIED; } }
static WERROR dsdb_syntax_DN_drsuapi_to_ldb(const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct drsuapi_DsReplicaAttribute *in, TALLOC_CTX *mem_ctx, struct ldb_message_element *out) { uint32_t i; out->flags = 0; out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName); W_ERROR_HAVE_NO_MEMORY(out->name); out->num_values = in->value_ctr.num_values; out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values); W_ERROR_HAVE_NO_MEMORY(out->values); for (i=0; i < out->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; NTSTATUS status; if (in->value_ctr.values[i].blob == NULL) { return WERR_FOOBAR; } if (in->value_ctr.values[i].blob->length == 0) { return WERR_FOOBAR; } status = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob, out->values, &id3, (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } /* TODO: handle id3.guid and id3.sid */ out->values[i] = data_blob_string_const(id3.dn); } return WERR_OK; }
/* convert a NDR formatted blob to a ldif formatted objectSid */ int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { struct dom_sid *sid; enum ndr_err_code ndr_err; sid = talloc(mem_ctx, struct dom_sid); if (sid == NULL) { return -1; } ndr_err = ndr_pull_struct_blob_all(in, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(sid); return -1; } *out = data_blob_string_const(dom_sid_string(mem_ctx, sid)); talloc_free(sid); if (out->data == NULL) { return -1; } return 0; }
static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status = NT_STATUS_OK; NTSTATUS result = NT_STATUS_OK; struct policy_handle handle; struct dcerpc_binding_handle *b = cli->binding_handle; uint32_t flags = EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ; uint32_t offset = 0; uint32_t number_of_bytes = 0; uint8_t *data = NULL; uint32_t sent_size = 0; uint32_t real_size = 0; if (argc < 2 || argc > 4) { printf("Usage: %s logname [offset] [number_of_bytes]\n", argv[0]); return NT_STATUS_OK; } if (argc >= 3) { offset = atoi(argv[2]); } if (argc >= 4) { number_of_bytes = atoi(argv[3]); data = talloc_array(mem_ctx, uint8_t, number_of_bytes); if (!data) { goto done; } } status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle); if (!NT_STATUS_IS_OK(status)) { return status; } do { enum ndr_err_code ndr_err; DATA_BLOB blob; struct EVENTLOGRECORD r; uint32_t size = 0; uint32_t pos = 0; status = dcerpc_eventlog_ReadEventLogW(b, mem_ctx, &handle, flags, offset, number_of_bytes, data, &sent_size, &real_size, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) && real_size > 0 ) { number_of_bytes = real_size; data = talloc_array(mem_ctx, uint8_t, real_size); if (!data) { goto done; } status = dcerpc_eventlog_ReadEventLogW(b, mem_ctx, &handle, flags, offset, number_of_bytes, data, &sent_size, &real_size, &result); if (!NT_STATUS_IS_OK(status)) { return status; } } if (!NT_STATUS_EQUAL(result, NT_STATUS_END_OF_FILE) && !NT_STATUS_IS_OK(result)) { goto done; } number_of_bytes = 0; size = IVAL(data, pos); while (size > 0) { blob = data_blob_const(data + pos, size); /* dump_data(0, blob.data, blob.length); */ ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_EVENTLOGRECORD); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto done; } NDR_PRINT_DEBUG(EVENTLOGRECORD, &r); pos += size; if (pos + 4 > sent_size) { break; } size = IVAL(data, pos); } offset++; } while (NT_STATUS_IS_OK(result)); done: dcerpc_eventlog_CloseEventLog(b, mem_ctx, &handle, &result); return status; }
/* convert a NDR formatted blob to a ldif formatted prefixMap */ static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx, const struct ldb_val *in, struct ldb_val *out) { struct prefixMapBlob *blob; enum ndr_err_code ndr_err; char *string; uint32_t i; if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) { int err; /* try to decode the blob as S4 prefixMap */ err = ldif_write_NDR(ldb, mem_ctx, in, out, sizeof(struct prefixMapBlob), (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob, (ndr_print_fn_t)ndr_print_prefixMapBlob, false); if (0 == err) { return err; } /* try parsing it as Windows PrefixMap value */ return ldif_write_NDR(ldb, mem_ctx, in, out, sizeof(struct drsuapi_MSPrefixMap_Ctr), (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr, (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr, true); } blob = talloc(mem_ctx, struct prefixMapBlob); if (blob == NULL) { return -1; } ndr_err = ndr_pull_struct_blob_all(in, blob, blob, (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { goto failed; } if (blob->version != PREFIX_MAP_VERSION_DSDB) { goto failed; } string = talloc_strdup(mem_ctx, ""); if (string == NULL) { goto failed; } for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { DATA_BLOB oid_blob; char *partial_oid = NULL; if (i > 0) { string = talloc_asprintf_append(string, ";"); } oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid, blob->ctr.dsdb.mappings[i].oid.length); if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) { DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X", blob->ctr.dsdb.mappings[i].id_prefix)); goto failed; } string = talloc_asprintf_append(string, "%u:%s", blob->ctr.dsdb.mappings[i].id_prefix, partial_oid); talloc_free(discard_const(partial_oid)); if (string == NULL) { goto failed; } } talloc_free(blob); *out = data_blob_string_const(string); return 0; failed: talloc_free(blob); return -1; }
NTSTATUS leases_db_add(const struct GUID *client_guid, const struct smb2_lease_key *lease_key, const struct file_id *id, const char *servicepath, const char *base_name, const char *stream_name) { TDB_DATA db_key, db_value; DATA_BLOB blob; struct db_record *rec; NTSTATUS status; bool ok; struct leases_db_value new_value; struct leases_db_file new_file; struct leases_db_value *value = NULL; enum ndr_err_code ndr_err; if (!leases_db_init(false)) { return NT_STATUS_INTERNAL_ERROR; } ok = leases_db_key(talloc_tos(), client_guid, lease_key, &db_key); if (!ok) { DEBUG(10, ("%s: leases_db_key failed\n", __func__)); return NT_STATUS_NO_MEMORY; } rec = dbwrap_fetch_locked(leases_db, talloc_tos(), db_key); TALLOC_FREE(db_key.dptr); if (rec == NULL) { return NT_STATUS_INTERNAL_ERROR; } db_value = dbwrap_record_get_value(rec); if (db_value.dsize != 0) { uint32_t i; DEBUG(10, ("%s: record exists\n", __func__)); value = talloc(talloc_tos(), struct leases_db_value); if (value == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } blob.data = db_value.dptr; blob.length = db_value.dsize; ndr_err = ndr_pull_struct_blob_all( &blob, value, value, (ndr_pull_flags_fn_t)ndr_pull_leases_db_value); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(10, ("%s: ndr_pull_struct_blob_failed: %s\n", __func__, ndr_errstr(ndr_err))); status = ndr_map_error2ntstatus(ndr_err); goto out; } /* id must be unique. */ for (i = 0; i < value->num_files; i++) { if (file_id_equal(id, &value->files[i].id)) { status = NT_STATUS_OBJECT_NAME_COLLISION; goto out; } } value->files = talloc_realloc(value, value->files, struct leases_db_file, value->num_files + 1); if (value->files == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } value->files[value->num_files].id = *id; value->files[value->num_files].servicepath = servicepath; value->files[value->num_files].base_name = base_name; value->files[value->num_files].stream_name = stream_name; value->num_files += 1; } else {
static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct ldb_message_element *in, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaAttribute *out) { uint32_t i; DATA_BLOB *blobs; if (attr->attributeID_id == 0xFFFFFFFF) { return WERR_FOOBAR; } out->attid = attr->attributeID_id; out->value_ctr.num_values = in->num_values; out->value_ctr.values = talloc_array(mem_ctx, struct drsuapi_DsAttributeValue, in->num_values); W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values); blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values); W_ERROR_HAVE_NO_MEMORY(blobs); for (i=0; i < in->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; enum ndr_err_code ndr_err; const DATA_BLOB *guid_blob, *sid_blob; struct ldb_dn *dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); out->value_ctr.values[i].blob = &blobs[i]; dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]); W_ERROR_HAVE_NO_MEMORY(dn); guid_blob = ldb_dn_get_extended_component(dn, "GUID"); ZERO_STRUCT(id3); if (guid_blob) { ndr_err = ndr_pull_struct_blob_all(guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, (ndr_pull_flags_fn_t)ndr_pull_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } sid_blob = ldb_dn_get_extended_component(dn, "SID"); if (sid_blob) { ndr_err = ndr_pull_struct_blob_all(sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } } id3.dn = ldb_dn_get_linearized(dn); ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } talloc_free(tmp_ctx); } return WERR_OK; }
static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb, const struct dsdb_schema *schema, const struct dsdb_attribute *attr, const struct drsuapi_DsReplicaAttribute *in, TALLOC_CTX *mem_ctx, struct ldb_message_element *out) { uint32_t i; int ret; out->flags = 0; out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName); W_ERROR_HAVE_NO_MEMORY(out->name); out->num_values = in->value_ctr.num_values; out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values); W_ERROR_HAVE_NO_MEMORY(out->values); for (i=0; i < out->num_values; i++) { struct drsuapi_DsReplicaObjectIdentifier3 id3; enum ndr_err_code ndr_err; DATA_BLOB guid_blob; struct ldb_dn *dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { W_ERROR_HAVE_NO_MEMORY(tmp_ctx); } if (in->value_ctr.values[i].blob == NULL) { talloc_free(tmp_ctx); return WERR_FOOBAR; } if (in->value_ctr.values[i].blob->length == 0) { talloc_free(tmp_ctx); return WERR_FOOBAR; } ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob, tmp_ctx, schema->iconv_convenience, &id3, (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } dn = ldb_dn_new(tmp_ctx, ldb, id3.dn); if (!dn) { talloc_free(tmp_ctx); /* If this fails, it must be out of memory, as it does not do much parsing */ W_ERROR_HAVE_NO_MEMORY(dn); } ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid, (ndr_push_flags_fn_t)ndr_push_GUID); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return WERR_FOOBAR; } talloc_free(guid_blob.data); if (id3.__ndr_size_sid) { DATA_BLOB sid_blob; ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid, (ndr_push_flags_fn_t)ndr_push_dom_sid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); talloc_free(tmp_ctx); return ntstatus_to_werror(status); } ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return WERR_FOOBAR; } } out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1)); talloc_free(tmp_ctx); } return WERR_OK; }
static NTSTATUS parse_supplemental_credentials(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct package_PrimaryKerberosCtr3 **pkb3, struct package_PrimaryKerberosCtr4 **pkb4) { NTSTATUS status; enum ndr_err_code ndr_err; struct supplementalCredentialsBlob scb; struct supplementalCredentialsPackage *scpk = NULL; DATA_BLOB scpk_blob; struct package_PrimaryKerberosBlob *pkb; bool newer_keys = false; uint32_t j; ndr_err = ndr_pull_struct_blob_all(blob, mem_ctx, &scb, (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto done; } if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) { if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb); } status = NT_STATUS_INVALID_PARAMETER; goto done; } for (j=0; j < scb.sub.num_packages; j++) { if (strcmp("Primary:Kerberos-Newer-Keys", scb.sub.packages[j].name) == 0) { scpk = &scb.sub.packages[j]; if (!scpk->data || !scpk->data[0]) { scpk = NULL; continue; } newer_keys = true; break; } else if (strcmp("Primary:Kerberos", scb.sub.packages[j].name) == 0) { /* * grab this but don't break here: * there might still be newer-keys ... */ scpk = &scb.sub.packages[j]; if (!scpk->data || !scpk->data[0]) { scpk = NULL; } } } if (!scpk) { /* no data */ status = NT_STATUS_OK; goto done; } scpk_blob = strhex_to_data_blob(mem_ctx, scpk->data); if (!scpk_blob.data) { status = NT_STATUS_NO_MEMORY; goto done; } pkb = talloc_zero(mem_ctx, struct package_PrimaryKerberosBlob); if (!pkb) { status = NT_STATUS_NO_MEMORY; goto done; } ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, pkb, (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto done; } if (!newer_keys && pkb->version != 3) { status = NT_STATUS_INVALID_PARAMETER; goto done; } if (newer_keys && pkb->version != 4) { status = NT_STATUS_INVALID_PARAMETER; goto done; } if (pkb->version == 4 && pkb4) { *pkb4 = &pkb->ctr.ctr4; } else if (pkb->version == 3 && pkb3) { *pkb3 = &pkb->ctr.ctr3; } status = NT_STATUS_OK; done: return status; }
static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob, uint64_t *pseq) { struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length}; NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq)); return NDR_ERR_SUCCESS; } static int share_mode_data_nofree_destructor(struct share_mode_data *d) { return -1; } static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx, const TDB_DATA id_key, DATA_BLOB *blob) { enum ndr_err_code ndr_err; struct share_mode_data *d; uint64_t sequence_number; void *ptr; struct file_id id; DATA_BLOB key; /* Ensure this is a locking_key record. */ if (id_key.dsize != sizeof(id)) { return NULL; } memcpy(&id, id_key.dptr, id_key.dsize); key = memcache_key(&id); ptr = memcache_lookup_talloc(NULL, SHARE_MODE_LOCK_CACHE, key); if (ptr == NULL) { DEBUG(10,("failed to find entry for key %s\n", file_id_string(mem_ctx, &id))); return NULL; } /* sequence number key is at start of blob. */ ndr_err = get_blob_sequence_number(blob, &sequence_number); if (ndr_err != NDR_ERR_SUCCESS) { /* Bad blob. Remove entry. */ DEBUG(10,("bad blob %u key %s\n", (unsigned int)ndr_err, file_id_string(mem_ctx, &id))); memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); return NULL; } d = (struct share_mode_data *)ptr; if (d->sequence_number != sequence_number) { DEBUG(10,("seq changed (cached 0x%llu) (new 0x%llu) " "for key %s\n", (unsigned long long)d->sequence_number, (unsigned long long)sequence_number, file_id_string(mem_ctx, &id))); /* Cache out of date. Remove entry. */ memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); return NULL; } /* Move onto mem_ctx. */ d = talloc_move(mem_ctx, &ptr); /* * Now we own d, prevent the cache from freeing it * when we delete the entry. */ talloc_set_destructor(d, share_mode_data_nofree_destructor); /* Remove from the cache. We own it now. */ memcache_delete(NULL, SHARE_MODE_LOCK_CACHE, key); /* And reset the destructor to none. */ talloc_set_destructor(d, NULL); DEBUG(10,("fetched entry for file %s seq 0x%llu key %s\n", d->base_name, (unsigned long long)d->sequence_number, file_id_string(mem_ctx, &id))); return d; } /******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx, const TDB_DATA key, const TDB_DATA dbuf) { struct share_mode_data *d; enum ndr_err_code ndr_err; uint32_t i; DATA_BLOB blob; blob.data = dbuf.dptr; blob.length = dbuf.dsize; /* See if we already have a cached copy of this key. */ d = share_mode_memcache_fetch(mem_ctx, key, &blob); if (d != NULL) { return d; } d = talloc(mem_ctx, struct share_mode_data); if (d == NULL) { DEBUG(0, ("talloc failed\n")); goto fail; } ndr_err = ndr_pull_struct_blob_all( &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n", ndr_errstr(ndr_err))); goto fail; } /* * Initialize the values that are [skip] in the idl. The NDR code does * not initialize them. */ for (i=0; i<d->num_share_modes; i++) { struct share_mode_entry *e = &d->share_modes[i]; e->stale = false; e->lease = NULL; if (e->op_type != LEASE_OPLOCK) { continue; } if (e->lease_idx >= d->num_leases) { continue; } e->lease = &d->leases[e->lease_idx]; } d->modified = false; d->fresh = false; if (DEBUGLEVEL >= 10) { DEBUG(10, ("parse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } return d; fail: TALLOC_FREE(d); return NULL; } /******************************************************************* Create a storable data blob from a modified share_mode_data struct. ********************************************************************/ static TDB_DATA unparse_share_modes(struct share_mode_data *d) { DATA_BLOB blob; enum ndr_err_code ndr_err; if (DEBUGLEVEL >= 10) { DEBUG(10, ("unparse_share_modes:\n")); NDR_PRINT_DEBUG(share_mode_data, d); } share_mode_memcache_delete(d); /* Update the sequence number. */ d->sequence_number += 1; remove_stale_share_mode_entries(d); if (d->num_share_modes == 0) { DEBUG(10, ("No used share mode found\n")); return make_tdb_data(NULL, 0); } ndr_err = ndr_push_struct_blob( &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { smb_panic("ndr_push_share_mode_lock failed"); } return make_tdb_data(blob.data, blob.length); }