static void do_locked1_del(struct db_record *rec, void *private_data) { struct do_locked1_state *state = (struct do_locked1_state *)private_data; state->status = dbwrap_record_delete(rec); }
static int regdb_normalize_keynames_fn(struct db_record *rec, void *private_data) { TALLOC_CTX *mem_ctx = talloc_tos(); const char *keyname; NTSTATUS status; TDB_DATA key; TDB_DATA value; struct db_context *db = (struct db_context *)private_data; key = dbwrap_record_get_key(rec); if (key.dptr == NULL || key.dsize == 0) { return 0; } value = dbwrap_record_get_value(rec); if (db == NULL) { DEBUG(0, ("regdb_normalize_keynames_fn: ERROR: " "NULL db context handed in via private_data\n")); return 1; } if (strncmp((const char *)key.dptr, REGDB_VERSION_KEYNAME, strlen(REGDB_VERSION_KEYNAME)) == 0) { return 0; } keyname = strchr((const char *)key.dptr, '/'); if (keyname) { keyname = talloc_string_sub(mem_ctx, (const char *)key.dptr, "/", "\\"); DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n", (const char *)key.dptr, keyname)); /* Delete the original record and store the normalized key */ status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("regdb_normalize_keynames_fn: " "tdb_delete for [%s] failed!\n", (const char *)key.dptr)); return 1; } status = dbwrap_store_bystring(db, keyname, value, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("regdb_normalize_keynames_fn: " "failed to store new record for [%s]!\n", keyname)); return 1; } } return 0; }
bool serverid_deregister(struct server_id id) { struct db_context *db; struct serverid_key key; struct db_record *rec; TDB_DATA tdbkey; NTSTATUS status; bool ret = false; db = serverid_db(); if (db == NULL) { return false; } serverid_fill_key(&id, &key); tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key)); rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey); if (rec == NULL) { DEBUG(1, ("Could not fetch_lock serverid.tdb record\n")); return false; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Deleting serverid.tdb record failed: %s\n", nt_errstr(status))); goto done; } ret = true; done: TALLOC_FREE(rec); return ret; }
NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key) { struct db_record *rec; NTSTATUS status; rec = dbwrap_fetch_locked(db, talloc_tos(), key); if (rec == NULL) { return NT_STATUS_NO_MEMORY; } status = dbwrap_record_delete(rec); TALLOC_FREE(rec); return status; }
static int share_mode_data_destructor(struct share_mode_data *d) { NTSTATUS status; TDB_DATA data; if (!d->modified) { return 0; } data = unparse_share_modes(d); if (data.dptr == NULL) { if (!d->fresh) { /* There has been an entry before, delete it */ status = dbwrap_record_delete(d->record); if (!NT_STATUS_IS_OK(status)) { char *errmsg; DEBUG(0, ("delete_rec returned %s\n", nt_errstr(status))); if (asprintf(&errmsg, "could not delete share " "entry: %s\n", nt_errstr(status)) == -1) { smb_panic("could not delete share" "entry"); } smb_panic(errmsg); } } goto done; } status = dbwrap_record_store(d->record, data, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { char *errmsg; DEBUG(0, ("store returned %s\n", nt_errstr(status))); if (asprintf(&errmsg, "could not store share mode entry: %s", nt_errstr(status)) == -1) { smb_panic("could not store share mode entry"); } smb_panic(errmsg); } done: return 0; }
NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key) { struct db_record *rec; NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); rec = dbwrap_fetch_locked(db, frame, key); if (rec == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } status = dbwrap_record_delete(rec); TALLOC_FREE(frame); return status; }
static int printer_list_clean_fn(struct db_record *rec, void *private_data) { struct printer_list_clean_state *state = (struct printer_list_clean_state *)private_data; uint32_t time_h, time_l; time_t refresh; char *name; char *comment; char *location; int ret; TDB_DATA key; TDB_DATA value; key = dbwrap_record_get_key(rec); /* skip anything that does not contain PL_DATA_FORMAT data */ if (strncmp((char *)key.dptr, PL_KEY_PREFIX, sizeof(PL_KEY_PREFIX)-1)) { return 0; } value = dbwrap_record_get_value(rec); ret = tdb_unpack(value.dptr, value.dsize, PL_DATA_FORMAT, &time_h, &time_l, &name, &comment, &location); if (ret == -1) { DEBUG(1, ("Failed to un pack printer data")); state->status = NT_STATUS_INTERNAL_DB_CORRUPTION; return -1; } SAFE_FREE(name); SAFE_FREE(comment); SAFE_FREE(location); refresh = (time_t)(((uint64_t)time_h << 32) + time_l); if (refresh < state->last_refresh) { state->status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(state->status)) { return -1; } } return 0; }
static int net_serverid_wipe_fn(struct db_record *rec, const struct server_id *id, uint32_t msg_flags, void *private_data) { NTSTATUS status; if (!procid_is_local(id)) { return 0; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { struct server_id_buf idbuf; DEBUG(1, ("Could not delete serverid.tdb record %s: %s\n", server_id_str_buf(*id, &idbuf), nt_errstr(status))); } return 0; }
static int net_serverid_wipe_fn(struct db_record *rec, const struct server_id *id, uint32_t msg_flags, void *private_data) { NTSTATUS status; if (id->vnn != get_my_vnn()) { return 0; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { char *str = server_id_str(talloc_tos(), id); DEBUG(1, ("Could not delete serverid.tdb record %s: %s\n", str, nt_errstr(status))); TALLOC_FREE(str); } return 0; }
/* save the notify array */ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec) { TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; enum ndr_err_code ndr_err; TALLOC_CTX *tmp_ctx; /* if possible, remove some depth arrays */ while (notify->array->num_depths > 0 && notify->array->depth[notify->array->num_depths-1].num_entries == 0) { notify->array->num_depths--; } /* we might just be able to delete the record */ if (notify->array->num_depths == 0) { return dbwrap_record_delete(rec); } tmp_ctx = talloc_new(notify); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, (ndr_push_flags_fn_t)ndr_push_notify_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); return ndr_map_error2ntstatus(ndr_err); } if (DEBUGLEVEL >= 10) { DEBUG(10, ("notify_save:\n")); NDR_PRINT_DEBUG(notify_array, notify->array); } dbuf.dptr = blob.data; dbuf.dsize = blob.length; status = dbwrap_record_store(rec, dbuf, TDB_REPLACE); talloc_free(tmp_ctx); return status; }
static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data) { NTSTATUS status; struct db_record *rec; TDB_DATA *key = (TDB_DATA *)private_data; rec = dbwrap_fetch_locked(db, talloc_tos(), *key); if (rec == NULL) { DEBUG(5, ("fetch_locked failed\n")); return NT_STATUS_NO_MEMORY; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status))); } talloc_free(rec); return status; }
static NTSTATUS acl_tdb_delete(vfs_handle_struct *handle, struct db_context *db, SMB_STRUCT_STAT *psbuf) { NTSTATUS status; struct file_id id = vfs_file_id_from_sbuf(handle->conn, psbuf); struct db_record *rec = acl_tdb_lock(talloc_tos(), db, &id); /* * If rec == NULL there's not much we can do about it */ if (rec == NULL) { DEBUG(10,("acl_tdb_delete: rec == NULL\n")); TALLOC_FREE(rec); return NT_STATUS_OK; } status = dbwrap_record_delete(rec); TALLOC_FREE(rec); return status; }
static bool upgrade_v2_to_v3_check_subkeylist(struct db_context *db, const char *key, const char *subkey) { static uint32_t zero = 0; static TDB_DATA empty_subkey_list = { .dptr = (unsigned char*)&zero, .dsize = sizeof(uint32_t), }; bool success = false; char *path = talloc_asprintf(talloc_tos(), "%s\\%s", key, subkey); strupper_m(path); if (!dbwrap_exists(db, string_term_tdb_data(path))) { NTSTATUS status; DEBUG(10, ("regdb_upgrade_v2_to_v3: writing subkey list [%s]\n", path)); status = dbwrap_store_bystring(db, path, empty_subkey_list, TDB_INSERT); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("regdb_upgrade_v2_to_v3: writing subkey list " "[%s] failed\n", path)); goto done; } } success = true; done: talloc_free(path); return success; } static bool upgrade_v2_to_v3_check_parent(struct db_context *db, const char *key) { const char *sep = strrchr_m(key, '\\'); if (sep != NULL) { char *pkey = talloc_strndup(talloc_tos(), key, sep-key); if (!dbwrap_exists(db, string_term_tdb_data(pkey))) { DEBUG(0, ("regdb_upgrade_v2_to_v3: missing subkey list " "[%s]\nrun \"net registry check\"\n", pkey)); } talloc_free(pkey); } return true; } #define IS_EQUAL(d,s) (((d).dsize == strlen(s)+1) && \ (strcmp((char*)(d).dptr, (s)) == 0)) #define STARTS_WITH(d,s) (((d).dsize > strlen(s)) && \ (strncmp((char*)(d).dptr, (s), strlen(s)) == 0)) #define SSTR(d) (int)(d).dsize , (char*)(d).dptr static int regdb_upgrade_v2_to_v3_fn(struct db_record *rec, void *private_data) { struct db_context *db = (struct db_context *)private_data; TDB_DATA key = dbwrap_record_get_key(rec); TDB_DATA val = dbwrap_record_get_value(rec); if (tdb_data_is_empty(key)) { return 0; } if (db == NULL) { DEBUG(0, ("regdb_upgrade_v2_to_v3_fn: ERROR: " "NULL db context handed in via private_data\n")); return 1; } if (IS_EQUAL(key, REGDB_VERSION_KEYNAME) || STARTS_WITH(key, REG_VALUE_PREFIX) || STARTS_WITH(key, REG_SECDESC_PREFIX)) { DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%.*s]\n", SSTR(key))); return 0; } if (STARTS_WITH(key, REG_SORTED_SUBKEYS_PREFIX)) { NTSTATUS status; /* Delete the deprecated sorted subkeys cache. */ DEBUG(10, ("regdb_upgrade_v2_to_v3: deleting [%.*s]\n", SSTR(key))); status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("regdb_upgrade_v2_to_v3: deleting [%.*s] " "failed!\n", SSTR(key))); return 1; } return 0; } if ( tdb_data_is_cstr(key) && hive_info((char*)key.dptr) != NULL ) { /* * Found a regular subkey list record. * Walk the list and create the list record for those * subkeys that don't already have one. */ TDB_DATA pos = val; char *subkey, *path = (char*)key.dptr; uint32_t num_items, found_items = 0; DEBUG(10, ("regdb_upgrade_v2_to_v3: scanning subkeylist of " "[%s]\n", path)); if (!tdb_data_read_uint32(&pos, &num_items)) { /* invalid or empty - skip */ return 0; } while (tdb_data_read_cstr(&pos, &subkey)) { found_items++; if (!upgrade_v2_to_v3_check_subkeylist(db, path, subkey)) { return 1; } if (!upgrade_v2_to_v3_check_parent(db, path)) { return 1; } } if (found_items != num_items) { DEBUG(0, ("regdb_upgrade_v2_to_v3: inconsistent subkey " "list [%s]\nrun \"net registry check\"\n", path)); } } else { DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping invalid [%.*s]\n" "run \"net registry check\"\n", SSTR(key))); } return 0; } static WERROR regdb_upgrade_v2_to_v3(struct db_context *db) { NTSTATUS status; WERROR werr; status = dbwrap_traverse(db, regdb_upgrade_v2_to_v3_fn, db, NULL); if (!NT_STATUS_IS_OK(status)) { werr = WERR_REG_IO_FAILURE; goto done; } werr = regdb_store_regdb_version(db, REGDB_VERSION_V3); done: return werr; }
static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec, bool *is_free, bool *was_free, TALLOC_CTX *mem_ctx, struct smbXsrv_tcon_global0 **_g) { TDB_DATA key; TDB_DATA val; DATA_BLOB blob; struct smbXsrv_tcon_globalB global_blob; enum ndr_err_code ndr_err; struct smbXsrv_tcon_global0 *global = NULL; bool exists; TALLOC_CTX *frame = talloc_stackframe(); *is_free = false; if (was_free) { *was_free = false; } if (_g) { *_g = NULL; } key = dbwrap_record_get_key(db_rec); val = dbwrap_record_get_value(db_rec); if (val.dsize == 0) { TALLOC_FREE(frame); *is_free = true; if (was_free) { *was_free = true; } return; } blob = data_blob_const(val.dptr, val.dsize); ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob, (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); DEBUG(1,("smbXsrv_tcon_global_verify_record: " "key '%s' ndr_pull_struct_blob - %s\n", hex_encode_talloc(frame, key.dptr, key.dsize), nt_errstr(status))); TALLOC_FREE(frame); return; } DEBUG(10,("smbXsrv_tcon_global_verify_record\n")); if (DEBUGLVL(10)) { NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob); } if (global_blob.version != SMBXSRV_VERSION_0) { DEBUG(0,("smbXsrv_tcon_global_verify_record: " "key '%s' use unsupported version %u\n", hex_encode_talloc(frame, key.dptr, key.dsize), global_blob.version)); NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob); TALLOC_FREE(frame); return; } global = global_blob.info.info0; exists = serverid_exists(&global->server_id); if (!exists) { struct server_id_buf idbuf; DEBUG(2,("smbXsrv_tcon_global_verify_record: " "key '%s' server_id %s does not exist.\n", hex_encode_talloc(frame, key.dptr, key.dsize), server_id_str_buf(global->server_id, &idbuf))); if (DEBUGLVL(2)) { NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob); } TALLOC_FREE(frame); dbwrap_record_delete(db_rec); *is_free = true; return; } if (_g) { *_g = talloc_move(mem_ctx, &global); } TALLOC_FREE(frame); }
NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid) { struct smbXsrv_tcon_table *table; struct db_record *local_rec = NULL; struct db_record *global_rec = NULL; NTSTATUS status; NTSTATUS error = NT_STATUS_OK; if (tcon->table == NULL) { return NT_STATUS_OK; } table = tcon->table; tcon->table = NULL; tcon->status = NT_STATUS_NETWORK_NAME_DELETED; global_rec = tcon->global->db_rec; tcon->global->db_rec = NULL; if (global_rec == NULL) { uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE]; TDB_DATA key; key = smbXsrv_tcon_global_id_to_key( tcon->global->tcon_global_id, key_buf); global_rec = dbwrap_fetch_locked(table->global.db_ctx, tcon->global, key); if (global_rec == NULL) { DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " "Failed to lock global key '%s'\n", tcon->global->tcon_global_id, tcon->global->share_name, hex_encode_talloc(global_rec, key.dptr, key.dsize))); error = NT_STATUS_INTERNAL_ERROR; } } if (global_rec != NULL) { status = dbwrap_record_delete(global_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(global_rec); DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " "failed to delete global key '%s': %s\n", tcon->global->tcon_global_id, tcon->global->share_name, hex_encode_talloc(global_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } } TALLOC_FREE(global_rec); local_rec = tcon->db_rec; if (local_rec == NULL) { uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE]; TDB_DATA key; key = smbXsrv_tcon_local_id_to_key(tcon->local_id, key_buf); local_rec = dbwrap_fetch_locked(table->local.db_ctx, tcon, key); if (local_rec == NULL) { DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " "Failed to lock local key '%s'\n", tcon->global->tcon_global_id, tcon->global->share_name, hex_encode_talloc(local_rec, key.dptr, key.dsize))); error = NT_STATUS_INTERNAL_ERROR; } } if (local_rec != NULL) { status = dbwrap_record_delete(local_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(local_rec); DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " "failed to delete local key '%s': %s\n", tcon->global->tcon_global_id, tcon->global->share_name, hex_encode_talloc(local_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } table->local.num_tcons -= 1; } if (tcon->db_rec == NULL) { TALLOC_FREE(local_rec); } tcon->db_rec = NULL; if (tcon->compat) { bool ok; ok = set_current_service(tcon->compat, 0, true); if (!ok) { status = NT_STATUS_INTERNAL_ERROR; DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): " "set_current_service() failed: %s\n", tcon->global->tcon_global_id, tcon->global->share_name, nt_errstr(status))); tcon->compat = NULL; return status; } close_cnum(tcon->compat, vuid); tcon->compat = NULL; } return error; }
/***************************************************************************** For idmap conversion: convert one record to new format Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid instead of the SID. *****************************************************************************/ static int convert_fn(struct db_record *rec, void *private_data) { struct winbindd_domain *domain; char *p; NTSTATUS status; struct dom_sid sid; uint32 rid; fstring keystr; fstring dom_name; TDB_DATA key; TDB_DATA key2; TDB_DATA value; struct convert_fn_state *s = (struct convert_fn_state *)private_data; key = dbwrap_record_get_key(rec); DEBUG(10,("Converting %s\n", (const char *)key.dptr)); p = strchr((const char *)key.dptr, '/'); if (!p) return 0; *p = 0; fstrcpy(dom_name, (const char *)key.dptr); *p++ = '/'; domain = find_domain_from_name(dom_name); if (domain == NULL) { /* We must delete the old record. */ DEBUG(0,("Unable to find domain %s\n", dom_name )); DEBUG(0,("deleting record %s\n", (const char *)key.dptr )); status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to delete record %s:%s\n", (const char *)key.dptr, nt_errstr(status))); s->failed = true; return -1; } return 0; } rid = atoi(p); sid_compose(&sid, &domain->sid, rid); sid_to_fstring(keystr, &sid); key2 = string_term_tdb_data(keystr); value = dbwrap_record_get_value(rec); status = dbwrap_store(s->db, key2, value, TDB_INSERT); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to add record %s:%s\n", (const char *)key2.dptr, nt_errstr(status))); s->failed = true; return -1; } status = dbwrap_store(s->db, value, key2, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to update record %s:%s\n", (const char *)value.dptr, nt_errstr(status))); s->failed = true; return -1; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to delete record %s:%s\n", (const char *)key.dptr, nt_errstr(status))); s->failed = true; return -1; } return 0; }
static int delete_fn(struct db_record *rec, void *priv) { dbwrap_record_delete(rec); return 0; }
NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now) { struct smbXsrv_open_table *table; struct db_record *local_rec = NULL; struct db_record *global_rec = NULL; NTSTATUS status; NTSTATUS error = NT_STATUS_OK; if (op->table == NULL) { return NT_STATUS_OK; } table = op->table; op->table = NULL; op->status = NT_STATUS_FILE_CLOSED; op->global->disconnect_time = now; server_id_set_disconnected(&op->global->server_id); global_rec = op->global->db_rec; op->global->db_rec = NULL; if (global_rec == NULL) { uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; TDB_DATA key; key = smbXsrv_open_global_id_to_key( op->global->open_global_id, key_buf); global_rec = dbwrap_fetch_locked(table->global.db_ctx, op->global, key); if (global_rec == NULL) { DEBUG(0, ("smbXsrv_open_close(0x%08x): " "Failed to lock global key '%s'\n", op->global->open_global_id, hex_encode_talloc(global_rec, key.dptr, key.dsize))); error = NT_STATUS_INTERNAL_ERROR; } } if (global_rec != NULL && op->global->durable) { /* * If it is a durable open we need to update the global part * instead of deleting it */ op->global->db_rec = global_rec; status = smbXsrv_open_global_store(op->global); if (NT_STATUS_IS_OK(status)) { /* * smbXsrv_open_global_store does the free * of op->global->db_rec */ global_rec = NULL; } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smbXsrv_open_close(0x%08x)" "smbXsrv_open_global_store() failed - %s\n", op->global->open_global_id, nt_errstr(status))); error = status; } if (NT_STATUS_IS_OK(status) && CHECK_DEBUGLVL(10)) { struct smbXsrv_openB open_blob; ZERO_STRUCT(open_blob); open_blob.version = SMBXSRV_VERSION_0; open_blob.info.info0 = op; DEBUG(10,("smbXsrv_open_close(0x%08x): " "stored disconnect\n", op->global->open_global_id)); NDR_PRINT_DEBUG(smbXsrv_openB, &open_blob); } } if (global_rec != NULL) { status = dbwrap_record_delete(global_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(global_rec); DEBUG(0, ("smbXsrv_open_close(0x%08x): " "failed to delete global key '%s': %s\n", op->global->open_global_id, hex_encode_talloc(global_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } } TALLOC_FREE(global_rec); local_rec = op->db_rec; if (local_rec == NULL) { uint8_t key_buf[SMBXSRV_OPEN_LOCAL_TDB_KEY_SIZE]; TDB_DATA key; key = smbXsrv_open_local_id_to_key(op->local_id, key_buf); local_rec = dbwrap_fetch_locked(table->local.db_ctx, op, key); if (local_rec == NULL) { DEBUG(0, ("smbXsrv_open_close(0x%08x): " "Failed to lock local key '%s'\n", op->global->open_global_id, hex_encode_talloc(local_rec, key.dptr, key.dsize))); error = NT_STATUS_INTERNAL_ERROR; } } if (local_rec != NULL) { status = dbwrap_record_delete(local_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(local_rec); DEBUG(0, ("smbXsrv_open_close(0x%08x): " "failed to delete local key '%s': %s\n", op->global->open_global_id, hex_encode_talloc(local_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } table->local.num_opens -= 1; } if (op->db_rec == NULL) { TALLOC_FREE(local_rec); } op->db_rec = NULL; if (op->compat) { op->compat->op = NULL; file_free(NULL, op->compat); op->compat = NULL; } return error; }
static int delete_record(struct db_record *rec, void *data) { NTSTATUS status = dbwrap_record_delete(rec); return NT_STATUS_IS_OK(status) ? 0 : -1; }
/* load the notify array */ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec) { TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; int seqnum; seqnum = dbwrap_get_seqnum(notify->db_recursive); if (seqnum == notify->seqnum && notify->array != NULL) { return NT_STATUS_OK; } notify->seqnum = seqnum; talloc_free(notify->array); notify->array = talloc_zero(notify, struct notify_array); NT_STATUS_HAVE_NO_MEMORY(notify->array); if (!rec) { status = dbwrap_fetch(notify->db_recursive, notify, notify->key, &dbuf); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } } else { dbuf = dbwrap_record_get_value(rec); } blob.data = (uint8 *)dbuf.dptr; blob.length = dbuf.dsize; status = NT_STATUS_OK; if (blob.length > 0) { enum ndr_err_code ndr_err; ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array, (ndr_pull_flags_fn_t)ndr_pull_notify_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { /* 1. log that we got a corrupt notify_array * 2. clear the variable the garbage was stored into to not trip * over it next time this method is entered with the same seqnum * 3. delete it from the database */ DEBUG(2, ("notify_array is corrupt, discarding it\n")); ZERO_STRUCTP(notify->array); if (rec != NULL) { dbwrap_record_delete(rec); } } else { if (DEBUGLEVEL >= 10) { DEBUG(10, ("notify_load:\n")); NDR_PRINT_DEBUG(notify_array, notify->array); } } } if (!rec) { talloc_free(dbuf.dptr); } return status; }
uint32_t smbXsrv_open_hash(struct smbXsrv_open *_open) { uint8_t buf[8+8+8]; uint32_t ret; TDB_DATA key; SBVAL(buf, 0, _open->global->open_persistent_id); SBVAL(buf, 8, _open->global->open_volatile_id); SBVAL(buf, 16, _open->global->open_time); key = (TDB_DATA) { .dptr = buf, .dsize = sizeof(buf) }; ret = tdb_jenkins_hash(&key); if (ret == 0) { ret = 1; } return ret; } static NTSTATUS smbXsrv_open_set_replay_cache(struct smbXsrv_open *op) { struct GUID *create_guid; struct GUID_txt_buf buf; char *guid_string; struct db_context *db = op->table->local.replay_cache_db_ctx; NTSTATUS status; if (!(op->flags & SMBXSRV_OPEN_NEED_REPLAY_CACHE)) { return NT_STATUS_OK; } if (op->flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE) { return NT_STATUS_OK; } create_guid = &op->global->create_guid; if (GUID_all_zero(create_guid)) { return NT_STATUS_OK; } guid_string = GUID_buf_string(create_guid, &buf); if (guid_string == NULL) { return NT_STATUS_INVALID_PARAMETER; } status = dbwrap_store_uint32_bystring(db, guid_string, op->local_id); if (NT_STATUS_IS_OK(status)) { op->flags |= SMBXSRV_OPEN_HAVE_REPLAY_CACHE; op->flags &= ~SMBXSRV_OPEN_NEED_REPLAY_CACHE; } return status; } static NTSTATUS smbXsrv_open_clear_replay_cache(struct smbXsrv_open *op) { struct GUID *create_guid; struct GUID_txt_buf buf; char *guid_string; struct db_context *db; NTSTATUS status; if (op->table == NULL) { return NT_STATUS_OK; } db = op->table->local.replay_cache_db_ctx; if (!(op->flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE)) { return NT_STATUS_OK; } create_guid = &op->global->create_guid; if (GUID_all_zero(create_guid)) { return NT_STATUS_OK; } guid_string = GUID_buf_string(create_guid, &buf); if (guid_string == NULL) { return NT_STATUS_INVALID_PARAMETER; } status = dbwrap_purge_bystring(db, guid_string); if (NT_STATUS_IS_OK(status)) { op->flags &= ~SMBXSRV_OPEN_HAVE_REPLAY_CACHE; } return status; } NTSTATUS smbXsrv_open_update(struct smbXsrv_open *op) { struct smbXsrv_open_table *table = op->table; NTSTATUS status; if (op->global->db_rec != NULL) { DEBUG(0, ("smbXsrv_open_update(0x%08x): " "Called with db_rec != NULL'\n", op->global->open_global_id)); return NT_STATUS_INTERNAL_ERROR; } op->global->db_rec = smbXsrv_open_global_fetch_locked( table->global.db_ctx, op->global->open_global_id, op->global /* TALLOC_CTX */); if (op->global->db_rec == NULL) { return NT_STATUS_INTERNAL_DB_ERROR; } status = smbXsrv_open_global_store(op->global); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smbXsrv_open_update: " "global_id (0x%08x) store failed - %s\n", op->global->open_global_id, nt_errstr(status))); return status; } status = smbXsrv_open_set_replay_cache(op); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("smbXsrv_open_set_replay_cache failed: %s\n", nt_errstr(status)); return status; } if (CHECK_DEBUGLVL(10)) { struct smbXsrv_openB open_blob; ZERO_STRUCT(open_blob); open_blob.version = SMBXSRV_VERSION_0; open_blob.info.info0 = op; DEBUG(10,("smbXsrv_open_update: global_id (0x%08x) stored\n", op->global->open_global_id)); NDR_PRINT_DEBUG(smbXsrv_openB, &open_blob); } return NT_STATUS_OK; } NTSTATUS smbXsrv_open_close(struct smbXsrv_open *op, NTTIME now) { struct smbXsrv_open_table *table; struct db_record *local_rec = NULL; struct db_record *global_rec = NULL; NTSTATUS status; NTSTATUS error = NT_STATUS_OK; error = smbXsrv_open_clear_replay_cache(op); if (!NT_STATUS_IS_OK(error)) { DBG_ERR("smbXsrv_open_clear_replay_cache failed: %s\n", nt_errstr(error)); } if (op->table == NULL) { return error; } table = op->table; op->table = NULL; op->status = NT_STATUS_FILE_CLOSED; op->global->disconnect_time = now; server_id_set_disconnected(&op->global->server_id); global_rec = op->global->db_rec; op->global->db_rec = NULL; if (global_rec == NULL) { global_rec = smbXsrv_open_global_fetch_locked( table->global.db_ctx, op->global->open_global_id, op->global /* TALLOC_CTX */); if (global_rec == NULL) { error = NT_STATUS_INTERNAL_ERROR; } } if (global_rec != NULL && op->global->durable) { /* * If it is a durable open we need to update the global part * instead of deleting it */ op->global->db_rec = global_rec; status = smbXsrv_open_global_store(op->global); if (NT_STATUS_IS_OK(status)) { /* * smbXsrv_open_global_store does the free * of op->global->db_rec */ global_rec = NULL; } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smbXsrv_open_close(0x%08x)" "smbXsrv_open_global_store() failed - %s\n", op->global->open_global_id, nt_errstr(status))); error = status; } if (NT_STATUS_IS_OK(status) && CHECK_DEBUGLVL(10)) { struct smbXsrv_openB open_blob; ZERO_STRUCT(open_blob); open_blob.version = SMBXSRV_VERSION_0; open_blob.info.info0 = op; DEBUG(10,("smbXsrv_open_close(0x%08x): " "stored disconnect\n", op->global->open_global_id)); NDR_PRINT_DEBUG(smbXsrv_openB, &open_blob); } } if (global_rec != NULL) { status = dbwrap_record_delete(global_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(global_rec); DEBUG(0, ("smbXsrv_open_close(0x%08x): " "failed to delete global key '%s': %s\n", op->global->open_global_id, hex_encode_talloc(global_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } } TALLOC_FREE(global_rec); local_rec = op->db_rec; if (local_rec == NULL) { local_rec = smbXsrv_open_local_fetch_locked(table->local.db_ctx, op->local_id, op /* TALLOC_CTX*/); if (local_rec == NULL) { error = NT_STATUS_INTERNAL_ERROR; } } if (local_rec != NULL) { status = dbwrap_record_delete(local_rec); if (!NT_STATUS_IS_OK(status)) { TDB_DATA key = dbwrap_record_get_key(local_rec); DEBUG(0, ("smbXsrv_open_close(0x%08x): " "failed to delete local key '%s': %s\n", op->global->open_global_id, hex_encode_talloc(local_rec, key.dptr, key.dsize), nt_errstr(status))); error = status; } table->local.num_opens -= 1; } if (op->db_rec == NULL) { TALLOC_FREE(local_rec); } op->db_rec = NULL; if (op->compat) { op->compat->op = NULL; file_free(NULL, op->compat); op->compat = NULL; } return error; } NTSTATUS smb1srv_open_table_init(struct smbXsrv_connection *conn) { uint32_t max_opens; /* * Allow a range from 1..65534. * * With real_max_open_files possible ids, * truncated to the SMB1 limit of 16-bit. * * 0 and 0xFFFF are no valid ids. */ max_opens = conn->client->sconn->real_max_open_files; max_opens = MIN(max_opens, UINT16_MAX - 1); return smbXsrv_open_table_init(conn, 1, UINT16_MAX - 1, max_opens); }
static int upgrade_v2_to_v3(struct db_record *rec, void *priv) { size_t prefix_len = strlen(SHARE_SECURITY_DB_KEY_PREFIX_STR); const char *servicename = NULL; char *c_servicename = NULL; char *newkey = NULL; bool *p_upgrade_ok = (bool *)priv; NTSTATUS status; TDB_DATA key; TDB_DATA value; key = dbwrap_record_get_key(rec); /* Is there space for a one character sharename ? */ if (key.dsize <= prefix_len+2) { return 0; } /* Does it start with the share key prefix ? */ if (memcmp(key.dptr, SHARE_SECURITY_DB_KEY_PREFIX_STR, prefix_len) != 0) { return 0; } /* Is it a null terminated string as a key ? */ if (key.dptr[key.dsize-1] != '\0') { return 0; } /* Bytes after the prefix are the sharename string. */ servicename = (char *)&key.dptr[prefix_len]; c_servicename = canonicalize_servicename(talloc_tos(), servicename); if (!c_servicename) { smb_panic("out of memory upgrading share security db from v2 -> v3"); } if (strcmp(servicename, c_servicename) == 0) { /* Old and new names match. No canonicalization needed. */ TALLOC_FREE(c_servicename); return 0; } /* Oops. Need to canonicalize name, delete old then store new. */ status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("upgrade_v2_to_v3: Failed to delete secdesc for " "%s: %s\n", (const char *)key.dptr, nt_errstr(status))); TALLOC_FREE(c_servicename); *p_upgrade_ok = false; return -1; } else { DEBUG(10, ("upgrade_v2_to_v3: deleted secdesc for " "%s\n", (const char *)key.dptr)); } if (!(newkey = talloc_asprintf(talloc_tos(), SHARE_SECURITY_DB_KEY_PREFIX_STR "%s", c_servicename))) { smb_panic("out of memory upgrading share security db from v2 -> v3"); } value = dbwrap_record_get_value(rec); status = dbwrap_store(share_db, string_term_tdb_data(newkey), value, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("upgrade_v2_to_v3: Failed to store secdesc for " "%s: %s\n", c_servicename, nt_errstr(status))); TALLOC_FREE(c_servicename); TALLOC_FREE(newkey); *p_upgrade_ok = false; return -1; } else { DEBUG(10, ("upgrade_v2_to_v3: stored secdesc for " "%s\n", newkey )); } TALLOC_FREE(newkey); TALLOC_FREE(c_servicename); return 0; }
NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) { NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *frame = talloc_stackframe(); struct smbXsrv_open_global0 *op = NULL; TDB_DATA val; struct db_record *rec; bool delete_open = false; uint32_t global_id = persistent_id & UINT32_MAX; rec = smbXsrv_open_global_fetch_locked(smbXsrv_open_global_db_ctx, global_id, frame); if (rec == NULL) { status = NT_STATUS_NOT_FOUND; goto done; } val = dbwrap_record_get_value(rec); if (val.dsize == 0) { DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "empty record in %s, skipping...\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); goto done; } status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " "failed to read record: %s\n", global_id, nt_errstr(status))); goto done; } if (server_id_is_disconnected(&op->server_id)) { struct timeval now, disconnect_time; int64_t tdiff; now = timeval_current(); nttime_to_timeval(&disconnect_time, op->disconnect_time); tdiff = usec_time_diff(&now, &disconnect_time); delete_open = (tdiff >= 1000*op->durable_timeout_msec); DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "disconnected at [%s] %us ago with " "timeout of %us -%s reached\n", global_id, nt_time_string(frame, op->disconnect_time), (unsigned)(tdiff/1000000), op->durable_timeout_msec / 1000, delete_open ? "" : " not")); } else if (!serverid_exists(&op->server_id)) { struct server_id_buf idbuf; DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "server[%s] does not exist\n", global_id, server_id_str_buf(op->server_id, &idbuf))); delete_open = true; } if (!delete_open) { goto done; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " "failed to delete record" "from %s: %s\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx), nt_errstr(status))); goto done; } DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "delete record from %s\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); done: talloc_free(frame); return status; }
static int share_mode_data_destructor(struct share_mode_data *d) { NTSTATUS status; TDB_DATA data; if (!d->modified) { return 0; } data = unparse_share_modes(d); if (data.dptr == NULL) { if (!d->fresh) { /* There has been an entry before, delete it */ status = dbwrap_record_delete(d->record); if (!NT_STATUS_IS_OK(status)) { char *errmsg; DEBUG(0, ("delete_rec returned %s\n", nt_errstr(status))); if (asprintf(&errmsg, "could not delete share " "entry: %s\n", nt_errstr(status)) == -1) { smb_panic("could not delete share" "entry"); } smb_panic(errmsg); } } /* * Nothing to store in cache - allow the normal * release of record lock and memory free. */ return 0; } status = dbwrap_record_store(d->record, data, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { char *errmsg; DEBUG(0, ("store returned %s\n", nt_errstr(status))); if (asprintf(&errmsg, "could not store share mode entry: %s", nt_errstr(status)) == -1) { smb_panic("could not store share mode entry"); } smb_panic(errmsg); } /* * Release the record lock before putting in the cache. */ TALLOC_FREE(d->record); /* * Reparent d into the in-memory cache so it can be reused if the * sequence number matches. See parse_share_modes() * for details. */ share_mode_memcache_store(d); return -1; }