コード例 #1
0
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);
}
コード例 #2
0
ファイル: reg_backend_db.c プロジェクト: ekohl/samba
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;
}
コード例 #3
0
ファイル: serverid.c プロジェクト: Gazzonyx/samba
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;
}
コード例 #4
0
ファイル: dbwrap.c プロジェクト: srimalik/samba
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;
}
コード例 #5
0
ファイル: share_mode_lock.c プロジェクト: ebrainte/Samba
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;
}
コード例 #6
0
ファイル: dbwrap.c プロジェクト: abartlet/samba-old
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;
}
コード例 #7
0
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;
}
コード例 #8
0
ファイル: net_serverid.c プロジェクト: DanilKorotenko/samba
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;
}
コード例 #9
0
ファイル: net_serverid.c プロジェクト: AIdrifter/samba
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;
}
コード例 #10
0
ファイル: notify_internal.c プロジェクト: srimalik/samba
/*
  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;
}
コード例 #11
0
ファイル: dbwrap_util.c プロジェクト: ebrainte/Samba
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;
}
コード例 #12
0
ファイル: vfs_acl_tdb.c プロジェクト: encukou/samba
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;
}
コード例 #13
0
ファイル: reg_backend_db.c プロジェクト: ekohl/samba
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;
}
コード例 #14
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
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);
}
コード例 #15
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
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;
}
コード例 #16
0
/*****************************************************************************
 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;
}
コード例 #17
0
static int delete_fn(struct db_record *rec, void *priv)
{
	dbwrap_record_delete(rec);
	return 0;
}
コード例 #18
0
ファイル: smbXsrv_open.c プロジェクト: hef/samba
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;
}
コード例 #19
0
ファイル: dbwrap.c プロジェクト: srimalik/samba
static int delete_record(struct db_record *rec, void *data)
{
	NTSTATUS status = dbwrap_record_delete(rec);
	return NT_STATUS_IS_OK(status) ? 0 : -1;
}
コード例 #20
0
ファイル: notify_internal.c プロジェクト: srimalik/samba
/*
  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;
}
コード例 #21
0
ファイル: smbXsrv_open.c プロジェクト: DanilKorotenko/samba
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);
}
コード例 #22
0
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;
}
コード例 #23
0
ファイル: smbXsrv_open.c プロジェクト: DanilKorotenko/samba
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;
}
コード例 #24
0
ファイル: share_mode_lock.c プロジェクト: Gazzonyx/samba
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;
}