Ejemplo n.º 1
0
struct blob *blob_parse(const char *blob, size_t len, const unsigned char key[KDF_HASH_LEN], const struct private_key *private_key)
{
	struct blob_pos blob_pos = { .data = blob, .len = len };
	struct chunk chunk;
	struct account *account, **next_account;
	struct field *field, **next_field = NULL;
	struct share *last_share = NULL;
	struct blob *parsed;
	_cleanup_free_ char *versionstr = NULL;

	parsed = new0(struct blob, 1);
	parsed->local_version = false;
	next_account = &parsed->account_head;

	while (read_chunk(&blob_pos, &chunk)) {
		if (!strcmp(chunk.name, "LPAV")) {
			versionstr = xstrndup(chunk.data, chunk.len);
			parsed->version = strtoull(versionstr, NULL, 10);
		} else if (!strcmp(chunk.name, "ACCT")) {
			account = account_parse(&chunk, last_share ? last_share->key : key);
			if (!account)
				goto error;
			share_assign(last_share, &account->share);

			*next_account = account;
			next_account = &account->next;

			next_field = &account->field_head;
		} else if (!strcmp(chunk.name, "ACFL") || !strcmp(chunk.name, "ACOF")) {
			if (!next_field)
				goto error;

			field = field_parse(&chunk, last_share ? last_share->key : key);
			if (!field)
				goto error;

			*next_field = field;
			next_field = &field->next;
		} else if (!strcmp(chunk.name, "LOCL"))
			parsed->local_version = true;
		else if (!strcmp(chunk.name, "SHAR")) {
			share_free(last_share);
			share_assign(share_parse(&chunk, private_key), &last_share);
		}
	}

	if (!versionstr)
		goto error;
	if (!parsed->account_head)
		goto error;
	share_free(last_share);
	return parsed;

error:
	share_free(last_share);
	blob_free(parsed);
	return NULL;
}
Ejemplo n.º 2
0
void account_free(struct account *account)
{
	if (!account)
		return;

	free(account->id);
	free(account->name);
	free(account->group);
	free(account->fullname);
	free(account->url);
	free(account->username);
	free(account->password);
	free(account->note);
	free(account->name_encrypted);
	free(account->group_encrypted);
	free(account->username_encrypted);
	free(account->password_encrypted);
	free(account->note_encrypted);
	for (struct field *field = account->field_head, *next_field = NULL; field; field = next_field) {
		next_field = field->next;
		field_free(field);
	}
	share_free(account->share);
	free(account);
}
Ejemplo n.º 3
0
static struct share *share_parse(struct chunk *chunk, const struct private_key *private_key)
{
	struct share *parsed = new0(struct share, 1);
	struct item item;
	_cleanup_free_ char *ciphertext = NULL;
	_cleanup_free_ char *hex_key = NULL;
	_cleanup_free_ unsigned char *key = NULL;
	_cleanup_free_ char *base64_name = NULL;
	size_t len;

	if (!private_key)
		goto error;

	if (chunk->len) {
		parsed->chunk_len = chunk->len;
		parsed->chunk = xmalloc(chunk->len);
		memcpy(parsed->chunk, chunk->data, chunk->len);
	}

	entry_plain(id);

	if (!read_item(chunk, &item) || item.len == 0 || item.len % 2 != 0)
		goto error;
	hex_to_bytes(item.data, &ciphertext);
	hex_key = cipher_rsa_decrypt(ciphertext, item.len / 2, private_key);
	if (!hex_key)
		goto error;
	len = strlen(hex_key);
	if (len % 2 != 0)
		goto error;
	len /= 2;
	if (len != KDF_HASH_LEN)
		goto error;
	hex_to_bytes(hex_key, (char **)&key);
	mlock(parsed->key, KDF_HASH_LEN);
	memcpy(parsed->key, key, KDF_HASH_LEN);

	base64_name = read_plain_string(chunk);
	parsed->name = cipher_aes_decrypt_base64(base64_name, parsed->key);
	if (!parsed->name)
		goto error;

	entry_boolean(readonly);

	return parsed;

error:
	share_free(parsed);
	return NULL;
}
Ejemplo n.º 4
0
/* Called by ares library for each result. */
static void result_callback (ASSearch *search, ASResult *r, as_bool duplicate)
{
	Share *share;
	char *url, *filename, *user;

	if (!r)
	{
		AS_DBG_1 ("Search complete. Id: %d.", search->id);

		/* Tell giFT we're finished. */
		PROTO->search_complete (PROTO, search->udata);

		/* The above does _not_ make giFT call asp_cb_search_cancel() so
		 * remove the search now.
		 */
		if (!as_searchman_remove (AS->searchman, search))
		{
			AS_ERR ("Failed to remove complete search");
			assert (0);
		}
		return;
	}

	/* Create a share object for giFT. */
	if (!(share = share_new (NULL)))
		return;

	share->p    = PROTO;
	share->size = r->filesize;
	filename    = r->filename;

	/* Try to find file name and size in hash table if none was returned. */
	if (search->type == SEARCH_LOCATE && (!filename || share->size == 0))
	{
		size_t size;
		char *name;

		/* Lookup this hash in the evil hash map to find the
		 * size and filename for giFT.
		 */
		if (asp_hashmap_lookup (r->hash, &name, &size))
		{
			if (share->size == 0)
				share->size = size;

			if (!filename && name && *name)
				filename = name;
		}
	}

	/* If we still don't have a file name fake one to prevent things from
	 * blowing up elsewhere.
	 */
	if (!filename)
		filename = "<Unknown>";

	share_set_path (share, filename);
	share_set_mime (share, mime_type (filename));
	share_set_hash (share, "SHA1", r->hash->data, AS_HASH_SIZE, FALSE);

	/* Add meta data. */
	if (r->meta)
		as_meta_foreach_tag (r->meta, (ASMetaForeachFunc)meta_to_gift, share);

	/* Create the url giFT will pass back to us on download. */
	if (!(url = as_source_serialize (r->source)))
	{
		AS_ERR_1 ("Couldn't serialize source '%s'",
		          as_source_str (r->source));
		share_free (share);
		return;
	}

	/* Assemble username@ip string. */
	if (STRING_NULL (r->source->username))
		user = stringf_dup ("%s@%s", r->source->username, 
		                    net_ip_str (r->source->host));
	else
		user = gift_strdup (net_ip_str (r->source->host));

	/* Send the result to giFT. */
	PROTO->search_result (PROTO, search->udata, user, NULL, url, 1, share);

	free (user);
	free (url);
	share_free (share);
}