コード例 #1
0
ファイル: pdb_tdb.c プロジェクト: Alexander--/samba
static int backup_copy_fn(struct db_record *orig_rec, void *state)
{
	struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
	struct db_record *new_rec;
	NTSTATUS status;
	TDB_DATA key;
	TDB_DATA value;

	key = dbwrap_record_get_key(orig_rec);

	new_rec = dbwrap_fetch_locked(bs->new_db, talloc_tos(), key);
	if (new_rec == NULL) {
		bs->success = false;
		return 1;
	}

	value = dbwrap_record_get_value(orig_rec);

	status = dbwrap_record_store(new_rec, value, TDB_INSERT);

	TALLOC_FREE(new_rec);

	if (!NT_STATUS_IS_OK(status)) {
		bs->success = false;
                return 1;
        }
        return 0;
}
コード例 #2
0
ファイル: serverid.c プロジェクト: Gazzonyx/samba
static bool serverid_rec_parse(const struct db_record *rec,
			       struct server_id *id, uint32_t *msg_flags)
{
	struct serverid_key key;
	struct serverid_data data;
	TDB_DATA tdbkey;
	TDB_DATA tdbdata;

	tdbkey = dbwrap_record_get_key(rec);
	tdbdata = dbwrap_record_get_value(rec);

	if (tdbkey.dsize != sizeof(key)) {
		DEBUG(1, ("Found invalid key length %d in serverid.tdb\n",
			  (int)tdbkey.dsize));
		return false;
	}
	if (tdbdata.dsize != sizeof(data)) {
		DEBUG(1, ("Found invalid value length %d in serverid.tdb\n",
			  (int)tdbdata.dsize));
		return false;
	}

	memcpy(&key, tdbkey.dptr, sizeof(key));
	memcpy(&data, tdbdata.dptr, sizeof(data));

	id->pid = key.pid;
	id->task_id = key.task_id;
	id->vnn = key.vnn;
	id->unique_id = data.unique_id;
	*msg_flags = data.msg_flags;
	return true;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: serverid.c プロジェクト: sprymak/samba
bool serverid_register_msg_flags(const struct server_id id, bool do_reg,
				 uint32_t msg_flags)
{
	struct db_context *db;
	struct serverid_key key;
	struct serverid_data *data;
	struct db_record *rec;
	TDB_DATA tdbkey;
	TDB_DATA value;
	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;
	}

	value = dbwrap_record_get_value(rec);

	if (value.dsize != sizeof(struct serverid_data)) {
		DEBUG(1, ("serverid record has unexpected size %d "
			  "(wanted %d)\n", (int)value.dsize,
			  (int)sizeof(struct serverid_data)));
		goto done;
	}

	data = (struct serverid_data *)value.dptr;

	if (do_reg) {
		data->msg_flags |= msg_flags;
	} else {
		data->msg_flags &= ~msg_flags;
	}

	status = dbwrap_record_store(rec, value, 0);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Storing serverid.tdb record failed: %s\n",
			  nt_errstr(status)));
		goto done;
	}
	ret = true;
done:
	TALLOC_FREE(rec);
	return ret;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: share_mode_lock.c プロジェクト: ebrainte/Samba
static struct share_mode_lock *get_share_mode_lock_internal(
	TALLOC_CTX *mem_ctx, struct file_id id,
	const char *servicepath, const struct smb_filename *smb_fname,
	const struct timespec *old_write_time)
{
	struct share_mode_lock *lck;
	struct share_mode_data *d;
	struct db_record *rec;
	TDB_DATA key = locking_key(&id);
	TDB_DATA value;

	rec = dbwrap_fetch_locked(lock_db, mem_ctx, key);
	if (rec == NULL) {
		DEBUG(3, ("Could not lock share entry\n"));
		return NULL;
	}

	value = dbwrap_record_get_value(rec);

	if (value.dptr == NULL) {
		d = fresh_share_mode_lock(mem_ctx, servicepath, smb_fname,
					  old_write_time);
	} else {
		d = parse_share_modes(mem_ctx, value);
	}

	if (d == NULL) {
		DEBUG(5, ("get_share_mode_lock_internal: "
			"Could not get share mode lock\n"));
		TALLOC_FREE(rec);
		return NULL;
	}
	d->id = id;
	d->record = talloc_move(d, &rec);
	talloc_set_destructor(d, share_mode_data_destructor);

	lck = talloc(mem_ctx, struct share_mode_lock);
	if (lck == NULL) {
		DEBUG(1, ("talloc failed\n"));
		TALLOC_FREE(d);
		return NULL;
	}
	lck->data = talloc_move(lck, &d);
	return lck;
}
コード例 #7
0
static int conn_traverse_fn(struct db_record *rec, void *private_data)
{
	TDB_DATA key;
	TDB_DATA value;
	struct conn_traverse_state *state =
		(struct conn_traverse_state *)private_data;

	key = dbwrap_record_get_key(rec);
	value = dbwrap_record_get_value(rec);

	if ((key.dsize != sizeof(struct connections_key))
	    || (value.dsize != sizeof(struct connections_data))) {
		return 0;
	}

	return state->fn(rec, (const struct connections_key *)key.dptr,
			 (const struct connections_data *)value.dptr,
			 state->private_data);
}
コード例 #8
0
ファイル: dbwrap_util.c プロジェクト: ebrainte/Samba
static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
						   void *private_data)
{
	struct db_record *rec;
	uint32_t val = (uint32_t)-1;
	uint32_t v_store;
	NTSTATUS ret;
	struct dbwrap_change_uint32_atomic_context *state;
	TDB_DATA value;

	state = (struct dbwrap_change_uint32_atomic_context *)private_data;

	rec = dbwrap_fetch_locked(db, talloc_tos(),
				  string_term_tdb_data(state->keystr));
	if (!rec) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	value = dbwrap_record_get_value(rec);

	if (value.dptr == NULL) {
		val = *(state->oldval);
	} else if (value.dsize == sizeof(val)) {
		val = IVAL(value.dptr, 0);
		*(state->oldval) = val;
	} else {
		ret = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	val += state->change_val;

	SIVAL(&v_store, 0, val);

	ret = dbwrap_record_store(rec,
				  make_tdb_data((const uint8_t *)&v_store,
						sizeof(v_store)),
				  TDB_REPLACE);

done:
	TALLOC_FREE(rec);
	return ret;
}
コード例 #9
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
static int smbXsrv_tcon_disconnect_all_callback(struct db_record *local_rec,
						void *private_data)
{
	struct smbXsrv_tcon_disconnect_all_state *state =
		(struct smbXsrv_tcon_disconnect_all_state *)private_data;
	TDB_DATA val;
	void *ptr = NULL;
	struct smbXsrv_tcon *tcon = NULL;
	uint64_t vuid;
	NTSTATUS status;

	val = dbwrap_record_get_value(local_rec);
	if (val.dsize != sizeof(ptr)) {
		status = NT_STATUS_INTERNAL_ERROR;
		if (NT_STATUS_IS_OK(state->first_status)) {
			state->first_status = status;
		}
		state->errors++;
		return 0;
	}

	memcpy(&ptr, val.dptr, val.dsize);
	tcon = talloc_get_type_abort(ptr, struct smbXsrv_tcon);

	vuid = state->vuid;
	if (vuid == 0 && tcon->compat) {
		vuid = tcon->compat->vuid;
	}

	tcon->db_rec = local_rec;
	status = smbXsrv_tcon_disconnect(tcon, vuid);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_IS_OK(state->first_status)) {
			state->first_status = status;
		}
		state->errors++;
		return 0;
	}

	return 0;
}
コード例 #10
0
ファイル: smbXsrv_open.c プロジェクト: DanilKorotenko/samba
static NTSTATUS smbXsrv_open_global_parse_record(TALLOC_CTX *mem_ctx,
						 struct db_record *rec,
						 struct smbXsrv_open_global0 **global)
{
	TDB_DATA key = dbwrap_record_get_key(rec);
	TDB_DATA val = dbwrap_record_get_value(rec);
	DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
	struct smbXsrv_open_globalB global_blob;
	enum ndr_err_code ndr_err;
	NTSTATUS status;
	TALLOC_CTX *frame = talloc_stackframe();

	ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_open_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:"
			 "key '%s' ndr_pull_struct_blob - %s\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 ndr_errstr(ndr_err)));
		status = ndr_map_error2ntstatus(ndr_err);
		goto done;
	}

	if (global_blob.version != SMBXSRV_VERSION_0) {
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:"
			 "key '%s' unsuported version - %d - %s\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 (int)global_blob.version,
			 nt_errstr(status)));
		goto done;
	}

	*global = talloc_move(mem_ctx, &global_blob.info.info0);
	status = NT_STATUS_OK;
done:
	talloc_free(frame);
	return status;
}
コード例 #11
0
static bool dbrec2map(const struct db_record *rec, GROUP_MAP *map)
{
	TDB_DATA key = dbwrap_record_get_key(rec);
	TDB_DATA value = dbwrap_record_get_value(rec);
	int ret = 0;
	fstring nt_name;
	fstring comment;

	if ((key.dsize < strlen(GROUP_PREFIX))
	    || (strncmp((char *)key.dptr, GROUP_PREFIX,
			GROUP_PREFIX_LEN) != 0)) {
		return False;
	}

	if (!string_to_sid(&map->sid, (const char *)key.dptr
			   + GROUP_PREFIX_LEN)) {
		return False;
	}

	ret = tdb_unpack(value.dptr, value.dsize, "ddff",
			  &map->gid, &map->sid_name_use,
			  &nt_name, &comment);

	if (ret == -1) {
		DEBUG(3, ("dbrec2map: tdb_unpack failure\n"));
		return false;
	}

	map->nt_name = talloc_strdup(map, nt_name);
	if (!map->nt_name) {
		return false;
	}
	map->comment = talloc_strdup(map, comment);
	if (!map->comment) {
		return false;
	}

	return true;
}
コード例 #12
0
static int printer_list_exec_fn(struct db_record *rec, void *private_data)
{
    struct printer_list_exec_state *state =
        (struct printer_list_exec_state *)private_data;
    uint32_t time_h, time_l;
    char *name;
    char *comment;
    char *location;
    int ret;
    TDB_DATA key;
    TDB_DATA value;

    key = dbwrap_record_get_key(rec);

    /* always skip PL_TIMESTAMP_KEY key */
    if (strequal((const char *)key.dptr, PL_TIMESTAMP_KEY)) {
        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;
    }

    state->fn(name, comment, location, state->private_data);

    SAFE_FREE(name);
    SAFE_FREE(comment);
    SAFE_FREE(location);
    return 0;
}
コード例 #13
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;
}
コード例 #14
0
ファイル: smbXsrv_version.c プロジェクト: miguelinux/samba
NTSTATUS smbXsrv_version_global_init(const struct server_id *server_id)
{
    const char *global_path = NULL;
    struct db_context *db_ctx = NULL;
    struct db_record *db_rec = NULL;
    TDB_DATA key;
    TDB_DATA val;
    DATA_BLOB blob;
    struct smbXsrv_version_globalB global_blob;
    enum ndr_err_code ndr_err;
    struct smbXsrv_version_global0 *global = NULL;
    uint32_t i;
    uint32_t num_valid = 0;
    struct smbXsrv_version_node0 *valid = NULL;
    struct smbXsrv_version_node0 *local_node = NULL;
    bool exists;
    NTSTATUS status;
    const char *key_string = "smbXsrv_version_global";
    TALLOC_CTX *frame;

    if (smbXsrv_version_global_db_ctx != NULL) {
        return NT_STATUS_OK;
    }

    frame = talloc_stackframe();

    global_path = lock_path("smbXsrv_version_global.tdb");
    if (global_path == NULL) {
        TALLOC_FREE(frame);
        return NT_STATUS_NO_MEMORY;
    }

    db_ctx = db_open(NULL, global_path,
                     0, /* hash_size */
                     TDB_DEFAULT |
                     TDB_CLEAR_IF_FIRST |
                     TDB_INCOMPATIBLE_HASH,
                     O_RDWR | O_CREAT, 0600,
                     DBWRAP_LOCK_ORDER_1,
                     DBWRAP_FLAG_NONE);
    if (db_ctx == NULL) {
        status = map_nt_error_from_unix_common(errno);
        DEBUG(0,("smbXsrv_version_global_init: "
                 "failed to open[%s] - %s\n",
                 global_path, nt_errstr(status)));
        TALLOC_FREE(frame);
        return status;
    }

    key = string_term_tdb_data(key_string);

    db_rec = dbwrap_fetch_locked(db_ctx, db_ctx, key);
    if (db_rec == NULL) {
        status = NT_STATUS_INTERNAL_DB_ERROR;
        DEBUG(0,("smbXsrv_version_global_init: "
                 "dbwrap_fetch_locked(%s) - %s\n",
                 key_string, nt_errstr(status)));
        TALLOC_FREE(frame);
        return status;
    }

    val = dbwrap_record_get_value(db_rec);
    if (val.dsize == 0) {
        global = talloc_zero(frame, struct smbXsrv_version_global0);
        if (global == NULL) {
            DEBUG(0,("smbXsrv_version_global_init: "
                     "talloc_zero failed - %s\n", __location__));
            TALLOC_FREE(frame);
            return NT_STATUS_NO_MEMORY;
        }
        ZERO_STRUCT(global_blob);
        global_blob.version = SMBXSRV_VERSION_CURRENT;
        global_blob.info.info0 = global;
    } else {
コード例 #15
0
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 {
コード例 #16
0
ファイル: dbwrap_torture.c プロジェクト: AIdrifter/samba
static void test_store_records(struct db_context *db, struct tevent_context *ev)
{
	TDB_DATA key;
	uint32_t *counters;
	TALLOC_CTX *tmp_ctx = talloc_stackframe();
	struct timeval start;

	key = string_term_tdb_data("testkey");

	start = timeval_current();
	while ((timelimit == 0) || (timeval_elapsed(&start) < timelimit)) {
		struct db_record *rec;
		TDB_DATA data;
		TDB_DATA value;
		int ret;
		NTSTATUS status;

		if (!no_trans) {
			if (verbose) DEBUG(1, ("starting transaction\n"));
			ret = dbwrap_transaction_start(db);
			if (ret != 0) {
				DEBUG(0, ("Failed to start transaction on node "
					  "%d\n", pnn));
				goto fail;
			}
			if (verbose) DEBUG(1, ("transaction started\n"));
			do_sleep(torture_delay);
		}

		if (verbose) DEBUG(1, ("calling fetch_lock\n"));
		rec = dbwrap_fetch_locked(db, tmp_ctx, key);
		if (rec == NULL) {
			DEBUG(0, ("Failed to fetch record\n"));
			goto fail;
		}
		if (verbose) DEBUG(1, ("fetched record ok\n"));
		do_sleep(torture_delay);
		value = dbwrap_record_get_value(rec);

		data.dsize = MAX(value.dsize, sizeof(uint32_t) * (pnn+1));
		data.dptr = (unsigned char *)talloc_zero_size(tmp_ctx,
							      data.dsize);
		if (data.dptr == NULL) {
			DEBUG(0, ("Failed to allocate data\n"));
			goto fail;
		}
		memcpy(data.dptr, value.dptr, value.dsize);

		counters = (uint32_t *)data.dptr;

		/* bump our counter */
		counters[pnn]++;

		if (verbose) DEBUG(1, ("storing data\n"));
		status = dbwrap_record_store(rec, data, TDB_REPLACE);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Failed to store record\n"));
			if (!no_trans) {
				ret = dbwrap_transaction_cancel(db);
				if (ret != 0) {
					DEBUG(0, ("Error cancelling transaction.\n"));
				}
			}
			goto fail;
		}
		talloc_free(rec);
		if (verbose) DEBUG(1, ("stored data ok\n"));
		do_sleep(torture_delay);

		if (!no_trans) {
			if (verbose) DEBUG(1, ("calling transaction_commit\n"));
			ret = dbwrap_transaction_commit(db);
			if (ret != 0) {
				DEBUG(0, ("Failed to commit transaction\n"));
				goto fail;
			}
			if (verbose) DEBUG(1, ("transaction committed\n"));
		}

		/* store the counters and verify that they are sane */
		if (verbose || (pnn == 0)) {
			if (!check_counters(db, data)) {
				goto fail;
			}
		}
		talloc_free(data.dptr);

		do_sleep(torture_delay);
	}

	goto done;

fail:
	success = false;

done:
	talloc_free(tmp_ctx);
	return;
}
コード例 #17
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
static NTSTATUS smbXsrv_tcon_global_store(struct smbXsrv_tcon_global0 *global)
{
	struct smbXsrv_tcon_globalB global_blob;
	DATA_BLOB blob = data_blob_null;
	TDB_DATA key;
	TDB_DATA val;
	NTSTATUS status;
	enum ndr_err_code ndr_err;

	/*
	 * TODO: if we use other versions than '0'
	 * we would add glue code here, that would be able to
	 * store the information in the old format.
	 */

	if (global->db_rec == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	key = dbwrap_record_get_key(global->db_rec);
	val = dbwrap_record_get_value(global->db_rec);

	ZERO_STRUCT(global_blob);
	global_blob.version = smbXsrv_version_global_current();
	if (val.dsize >= 8) {
		global_blob.seqnum = IVAL(val.dptr, 4);
	}
	global_blob.seqnum += 1;
	global_blob.info.info0 = global;

	ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
			(ndr_push_flags_fn_t)ndr_push_smbXsrv_tcon_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_tcon_global_store: key '%s' ndr_push - %s\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(global->db_rec);
		return status;
	}

	val = make_tdb_data(blob.data, blob.length);
	status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("smbXsrv_tcon_global_store: key '%s' store - %s\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(global->db_rec);
		return status;
	}

	if (DEBUGLVL(10)) {
		DEBUG(10,("smbXsrv_tcon_global_store: key '%s' stored\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize)));
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
	}

	TALLOC_FREE(global->db_rec);

	return NT_STATUS_OK;
}
コード例 #18
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
static NTSTATUS smbXsrv_tcon_create(struct smbXsrv_tcon_table *table,
				    enum protocol_types protocol,
				    struct server_id server_id,
				    NTTIME now,
				    struct smbXsrv_tcon **_tcon)
{
	struct db_record *local_rec = NULL;
	struct smbXsrv_tcon *tcon = NULL;
	void *ptr = NULL;
	TDB_DATA val;
	struct smbXsrv_tcon_global0 *global = NULL;
	NTSTATUS status;

	if (table->local.num_tcons >= table->local.max_tcons) {
		return NT_STATUS_INSUFFICIENT_RESOURCES;
	}

	tcon = talloc_zero(table, struct smbXsrv_tcon);
	if (tcon == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	tcon->table = table;
	tcon->status = NT_STATUS_INTERNAL_ERROR;
	tcon->idle_time = now;

	status = smbXsrv_tcon_global_allocate(table->global.db_ctx,
					      tcon, &global);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(tcon);
		return status;
	}
	tcon->global = global;

	if (protocol >= PROTOCOL_SMB2_02) {
		uint64_t id = global->tcon_global_id;
		uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
		TDB_DATA key;

		global->tcon_wire_id = id;

		tcon->local_id = global->tcon_global_id;

		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) {
			TALLOC_FREE(tcon);
			return NT_STATUS_NO_MEMORY;
		}

		val = dbwrap_record_get_value(local_rec);
		if (val.dsize != 0) {
			TALLOC_FREE(tcon);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}
	} else {

		status = smb1srv_tcon_local_allocate_id(table->local.db_ctx,
							table->local.lowest_id,
							table->local.highest_id,
							tcon,
							&local_rec,
							&tcon->local_id);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(tcon);
			return status;
		}

		global->tcon_wire_id = tcon->local_id;
	}

	global->creation_time = now;

	global->server_id = server_id;

	ptr = tcon;
	val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
	status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
	TALLOC_FREE(local_rec);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(tcon);
		return status;
	}
	table->local.num_tcons += 1;

	talloc_set_destructor(tcon, smbXsrv_tcon_destructor);

	status = smbXsrv_tcon_global_store(global);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("smbXsrv_tcon_create: "
			 "global_id (0x%08x) store failed - %s\n",
			 tcon->global->tcon_global_id,
			 nt_errstr(status)));
		TALLOC_FREE(tcon);
		return status;
	}

	if (DEBUGLVL(10)) {
		struct smbXsrv_tconB tcon_blob;

		ZERO_STRUCT(tcon_blob);
		tcon_blob.version = SMBXSRV_VERSION_0;
		tcon_blob.info.info0 = tcon;

		DEBUG(10,("smbXsrv_tcon_create: global_id (0x%08x) stored\n",
			 tcon->global->tcon_global_id));
		NDR_PRINT_DEBUG(smbXsrv_tconB, &tcon_blob);
	}

	*_tcon = tcon;
	return NT_STATUS_OK;
}
コード例 #19
0
ファイル: smbXsrv_tcon.c プロジェクト: Distrotech/samba
static NTSTATUS smb1srv_tcon_local_allocate_id(struct db_context *db,
					       uint32_t lowest_id,
					       uint32_t highest_id,
					       TALLOC_CTX *mem_ctx,
					       struct db_record **_rec,
					       uint32_t *_id)
{
	struct smb1srv_tcon_local_allocate_state state = {
		.lowest_id = lowest_id,
		.highest_id = highest_id,
		.last_id = 0,
		.useable_id = lowest_id,
		.status = NT_STATUS_INTERNAL_ERROR,
	};
	uint32_t i;
	uint32_t range;
	NTSTATUS status;
	int count = 0;

	*_rec = NULL;
	*_id = 0;

	if (lowest_id > highest_id) {
		return NT_STATUS_INSUFFICIENT_RESOURCES;
	}

	/*
	 * first we try randomly
	 */
	range = (highest_id - lowest_id) + 1;

	for (i = 0; i < (range / 2); i++) {
		uint32_t id;
		uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
		TDB_DATA key;
		TDB_DATA val;
		struct db_record *rec = NULL;

		id = generate_random() % range;
		id += lowest_id;

		if (id < lowest_id) {
			id = lowest_id;
		}
		if (id > highest_id) {
			id = highest_id;
		}

		key = smbXsrv_tcon_local_id_to_key(id, key_buf);

		rec = dbwrap_fetch_locked(db, mem_ctx, key);
		if (rec == NULL) {
			return NT_STATUS_INSUFFICIENT_RESOURCES;
		}

		val = dbwrap_record_get_value(rec);
		if (val.dsize != 0) {
			TALLOC_FREE(rec);
			continue;
		}

		*_rec = rec;
		*_id = id;
		return NT_STATUS_OK;
	}

	/*
	 * if the range is almost full,
	 * we traverse the whole table
	 * (this relies on sorted behavior of dbwrap_rbt)
	 */
	status = dbwrap_traverse_read(db, smb1srv_tcon_local_allocate_traverse,
				      &state, &count);
	if (NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_IS_OK(state.status)) {
			return NT_STATUS_INTERNAL_ERROR;
		}

		if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
			return state.status;
		}

		if (state.useable_id <= state.highest_id) {
			state.status = NT_STATUS_OK;
		} else {
			return NT_STATUS_INSUFFICIENT_RESOURCES;
		}
	} else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
		/*
		 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
		 *
		 * If we get anything else it is an error, because it
		 * means we did not manage to find a free slot in
		 * the db.
		 */
		return NT_STATUS_INSUFFICIENT_RESOURCES;
	}

	if (NT_STATUS_IS_OK(state.status)) {
		uint32_t id;
		uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
		TDB_DATA key;
		TDB_DATA val;
		struct db_record *rec = NULL;

		id = state.useable_id;

		key = smbXsrv_tcon_local_id_to_key(id, key_buf);

		rec = dbwrap_fetch_locked(db, mem_ctx, key);
		if (rec == NULL) {
			return NT_STATUS_INSUFFICIENT_RESOURCES;
		}

		val = dbwrap_record_get_value(rec);
		if (val.dsize != 0) {
			TALLOC_FREE(rec);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		*_rec = rec;
		*_id = id;
		return NT_STATUS_OK;
	}

	return state.status;
}

struct smbXsrv_tcon_local_fetch_state {
	struct smbXsrv_tcon *tcon;
	NTSTATUS status;
};

static void smbXsrv_tcon_local_fetch_parser(TDB_DATA key, TDB_DATA data,
					    void *private_data)
{
	struct smbXsrv_tcon_local_fetch_state *state =
		(struct smbXsrv_tcon_local_fetch_state *)private_data;
	void *ptr;

	if (data.dsize != sizeof(ptr)) {
		state->status = NT_STATUS_INTERNAL_DB_ERROR;
		return;
	}

	memcpy(&ptr, data.dptr, data.dsize);
	state->tcon = talloc_get_type_abort(ptr, struct smbXsrv_tcon);
	state->status = NT_STATUS_OK;
}

static NTSTATUS smbXsrv_tcon_local_lookup(struct smbXsrv_tcon_table *table,
					  uint32_t tcon_local_id,
					  NTTIME now,
					  struct smbXsrv_tcon **_tcon)
{
	struct smbXsrv_tcon_local_fetch_state state = {
		.tcon = NULL,
		.status = NT_STATUS_INTERNAL_ERROR,
	};
	uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
	TDB_DATA key;
	NTSTATUS status;

	*_tcon = NULL;

	if (tcon_local_id == 0) {
		return NT_STATUS_NETWORK_NAME_DELETED;
	}

	if (table == NULL) {
		/* this might happen before the end of negprot */
		return NT_STATUS_NETWORK_NAME_DELETED;
	}

	if (table->local.db_ctx == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	key = smbXsrv_tcon_local_id_to_key(tcon_local_id, key_buf);

	status = dbwrap_parse_record(table->local.db_ctx, key,
				     smbXsrv_tcon_local_fetch_parser,
				     &state);
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
		return NT_STATUS_NETWORK_NAME_DELETED;
	} else if (!NT_STATUS_IS_OK(status)) {
		return status;
	}
	if (!NT_STATUS_IS_OK(state.status)) {
		return state.status;
	}

	if (NT_STATUS_EQUAL(state.tcon->status, NT_STATUS_NETWORK_NAME_DELETED)) {
		return NT_STATUS_NETWORK_NAME_DELETED;
	}

	state.tcon->idle_time = now;

	*_tcon = state.tcon;
	return state.tcon->status;
}

static int smbXsrv_tcon_global_destructor(struct smbXsrv_tcon_global0 *global)
{
	return 0;
}

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);

static NTSTATUS smbXsrv_tcon_global_allocate(struct db_context *db,
					TALLOC_CTX *mem_ctx,
					struct smbXsrv_tcon_global0 **_global)
{
	uint32_t i;
	struct smbXsrv_tcon_global0 *global = NULL;
	uint32_t last_free = 0;
	const uint32_t min_tries = 3;

	*_global = NULL;

	global = talloc_zero(mem_ctx, struct smbXsrv_tcon_global0);
	if (global == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	talloc_set_destructor(global, smbXsrv_tcon_global_destructor);

	/*
	 * Here we just randomly try the whole 32-bit space
	 *
	 * We use just 32-bit, because we want to reuse the
	 * ID for SRVSVC.
	 */
	for (i = 0; i < UINT32_MAX; i++) {
		bool is_free = false;
		bool was_free = false;
		uint32_t id;
		uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE];
		TDB_DATA key;

		if (i >= min_tries && last_free != 0) {
			id = last_free;
		} else {
			id = generate_random();
		}
		if (id == 0) {
			id++;
		}
		if (id == UINT32_MAX) {
			id--;
		}

		key = smbXsrv_tcon_global_id_to_key(id, key_buf);

		global->db_rec = dbwrap_fetch_locked(db, mem_ctx, key);
		if (global->db_rec == NULL) {
			talloc_free(global);
			return NT_STATUS_INSUFFICIENT_RESOURCES;
		}

		smbXsrv_tcon_global_verify_record(global->db_rec,
						  &is_free,
						  &was_free,
						  NULL, NULL);

		if (!is_free) {
			TALLOC_FREE(global->db_rec);
			continue;
		}

		if (!was_free && i < min_tries) {
			/*
			 * The session_id is free now,
			 * but was not free before.
			 *
			 * This happens if a smbd crashed
			 * and did not cleanup the record.
			 *
			 * If this is one of our first tries,
			 * then we try to find a real free one.
			 */
			if (last_free == 0) {
				last_free = id;
			}
			TALLOC_FREE(global->db_rec);
			continue;
		}

		global->tcon_global_id = id;

		*_global = global;
		return NT_STATUS_OK;
	}

	/* should not be reached */
	talloc_free(global);
	return NT_STATUS_INTERNAL_ERROR;
}
コード例 #20
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);
}
コード例 #21
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;
}
コード例 #22
0
ファイル: pdb_tdb.c プロジェクト: Alexander--/samba
static int tdbsam_convert_one(struct db_record *rec, void *priv)
{
	struct tdbsam_convert_state *state =
		(struct tdbsam_convert_state *)priv;
	struct samu *user;
	TDB_DATA data;
	NTSTATUS status;
	bool ret;
	TDB_DATA key;
	TDB_DATA value;

	key = dbwrap_record_get_key(rec);

	if (key.dsize < USERPREFIX_LEN) {
		return 0;
	}
	if (strncmp((char *)key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
		return 0;
	}

	user = samu_new(talloc_tos());
	if (user == NULL) {
		DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
		state->success = false;
		return -1;
	}

	DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
		  "(version:%d)\n", (char *)key.dptr, state->from));

	value = dbwrap_record_get_value(rec);

	switch (state->from) {
	case 0:
		ret = init_samu_from_buffer(user, SAMU_BUFFER_V0,
					    (uint8_t *)value.dptr,
					    value.dsize);
		break;
	case 1:
		ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
					    (uint8_t *)value.dptr,
					    value.dsize);
		break;
	case 2:
		ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
					    (uint8_t *)value.dptr,
					    value.dsize);
		break;
	case 3:
		ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
					    (uint8_t *)value.dptr,
					    value.dsize);
		break;
	case 4:
		ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
					    (uint8_t *)value.dptr,
					    value.dsize);
		break;
	default:
		/* unknown tdbsam version */
		ret = False;
	}
	if (!ret) {
		DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
			 "from TDB (key:%s) (version:%d)\n", (char *)key.dptr,
			 state->from));
		TALLOC_FREE(user);
		state->success = false;
		return -1;
	}

	data.dsize = init_buffer_from_samu(&data.dptr, user, false);
	TALLOC_FREE(user);

	if (data.dsize == -1) {
		DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
			 "the new format\n"));
		state->success = false;
		return -1;
	}

	status = dbwrap_record_store(rec, data, TDB_MODIFY);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Could not store the new record: %s\n",
			  nt_errstr(status)));
		state->success = false;
		return -1;
	}

	return 0;
}
コード例 #23
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;
}
コード例 #24
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;
}
コード例 #25
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;
}