Пример #1
0
static void hmac_sha256_for_data(char *hash,
				 const unsigned char *key, size_t key_len,
				 const unsigned char *data, size_t data_len)
{
	unsigned char digest[EVP_MAX_MD_SIZE];
	unsigned int digest_len = 0;
	char *digest_str;
	unsigned int i;

	if (data == NULL) {
		hash_set_zeros(hash);
		return;
	}

	if (HMAC(EVP_sha256(), (const void *)key, key_len, data, data_len, digest, &digest_len) == NULL) {
		hash_set_zeros(hash);
		return;
	}

	digest_str = calloc((digest_len * 2) + 1, sizeof(char));
	if (digest_str == NULL) {
		abort();
	}

	for (i = 0; i < digest_len; i++) {
		sprintf(&digest_str[i * 2], "%02x", (unsigned int)digest[i]);
	}

	hash_assign(digest_str, hash);
	free(digest_str);
}
Пример #2
0
static void hash_set_ones(char *hash)
{
	hash_assign("1111111111111111111111111111111111111111111111111111111111111111", hash);
}
Пример #3
0
int match_manifests(struct manifest *m1, struct manifest *m2)
{
	GList *list1, *list2;
	struct file *file1, *file2;
	int must_sort = 0;
	int count = 0;
	int first = 1;

	if (!m1) {
		printf("Matching manifests up failed: No old manifest!\n");
		return -1;
	}

	if (!m2) {
		printf("Matching manifests up failed: No new manifest!\n");
		return -1;
	}

	m1->files = g_list_sort(m1->files, file_sort_filename);
	m2->files = g_list_sort(m2->files, file_sort_filename);

	list1 = g_list_first(m1->files);
	list2 = g_list_first(m2->files);

	while (list1 && list2) {
		int ret;
		file1 = list1->data;
		file2 = list2->data;

		file1->peer = NULL;
		file2->peer = NULL;

		ret = strcmp(file1->filename, file2->filename);
		if (ret == 0) {
			if (file1->is_deleted && file2->is_deleted && file1->is_rename) {
				file2->is_rename = file1->is_rename;
				hash_assign(file1->hash, file2->hash);
			}

			if (hash_compare(file1->hash, file2->hash) &&
			    file1->is_dir == file2->is_dir &&
			    file1->is_link == file2->is_link &&
			    file1->is_deleted == file2->is_deleted &&
			    file1->is_file == file2->is_file &&
			    file1->is_config == file2->is_config &&
			    file1->is_state == file2->is_state &&
			    file1->is_boot == file2->is_boot &&
			    file1->last_change >= minversion) {
				file2->last_change = file1->last_change;
				file2->is_rename = file1->is_rename;
			} else {
				account_changed_file();
				if (first) {
					LOG(file1, "file changed", "");
					first = 0;
				}
				count++;
			}

			if (!file1->is_deleted || file2->is_deleted) {
				file1->peer = file2;
				file2->peer = file1;
			}

			list1 = g_list_next(list1);
			list2 = g_list_next(list2);
			continue;
		}
		if (first) {
			LOG(file1, "file added? ", "(file2 is %s)", file2->filename);
			first = 0;
		}
		if (ret < 0) {
			struct file *file3;
			/*
			 * if we get here, file1 got deleted... what we must do
			 * is add a file entry for it in the target list.
			 * However, since we're currently walking the list we
			 * HAVE to prepend the entry.. and mark for sort at the
			 * end.
			 */
			file3 = calloc(1, sizeof(struct file));
			if (file3 == NULL) {
				assert(0);
			}

			file3->filename = strdup(file1->filename);
			hash_set_zeros(file3->hash);
			file3->is_deleted = 1;
			file3->is_config = file1->is_config;
			file3->is_state = file1->is_state;
			file3->is_boot = file1->is_boot;

			if (!file1->is_deleted) {
				file3->last_change = m2->version;
			} else {
				file3->last_change = file1->last_change;
				file3->is_rename = file1->is_rename;
				hash_assign(file1->hash, file3->hash);
			}

			file3->peer = file1;
			file1->peer = file3;

			list1 = g_list_next(list1);
			m2->files = g_list_prepend(m2->files, file3);
			m2->count++;
			if (!file1->is_deleted) {
				account_deleted_file();
				count++;
				if (first) {
					LOG(file1, "file got deleted", "");
					first = 0;
				}
			}
			must_sort = 1;
			continue;
		}
		/* if we get here, ret is > 0, which means this is a new file added */
		/* all we do is advance the pointer */
		account_new_file();
		list2 = g_list_next(list2);
		count++;
	}

	/* now deal with the tail ends */
	while (list1) {
		file1 = list1->data;

		struct file *file3;

		if (first) {
			LOG(file1, "file changed tail", "");
			first = 0;
		}
		count++;
		/*
		 * if we get here, file1 got deleted... what we must do is add
		 * a file entry for it in the target list.  However, since
		 * we're currently walking the list we HAVE to prepend the
		 * entry.. and mark for sort at the end.
		 */
		file3 = calloc(1, sizeof(struct file));
		if (file3 == NULL) {
			assert(0);
		}

		file3->filename = strdup(file1->filename);
		hash_set_zeros(file3->hash);
		file3->is_deleted = 1;
		file3->is_config = file1->is_config;
		file3->is_state = file1->is_state;
		file3->is_boot = file1->is_boot;

		if (!file1->is_deleted) {
			file3->last_change = m2->version;
		} else {
			file3->last_change = file1->last_change;
			file3->is_rename = file1->is_rename;
			hash_assign(file1->hash, file3->hash);
		}

		file3->peer = file1;
		file1->peer = file3;

		list1 = g_list_next(list1);
		m2->files = g_list_prepend(m2->files, file3);
		m2->count++;
		if (!file1->is_deleted) {
			account_deleted_file();
		}
		must_sort = 1;
	}

	while (list2) {
		account_new_file();
		list2 = g_list_next(list2);
		if (first) {
			first = 0;
		}
		count++;
	}
	if (must_sort) {
		m2->files = g_list_sort(m2->files, file_sort_filename);
	}

	return count;
}
Пример #4
0
static void hash_set_zeros(char *hash)
{
	hash_assign("0000000000000000000000000000000000000000000000000000000000000000", hash);
}
Пример #5
0
struct manifest *manifest_from_file(int version, char *component)
{
	FILE *infile;
	GList *includes = NULL;
	char line[8192], *c, *c2;
	int count = 0;
	struct manifest *manifest;
	char *filename, *conf;
	int previous = 0;
	unsigned long long int format_number;

	conf = config_output_dir();
	if (conf == NULL) {
		assert(0);
	}

	string_or_die(&filename, "%s/%i/Manifest.%s", conf, version, component);
	free(conf);

	LOG(NULL, "Reading manifest", "%s", filename);
	infile = fopen(filename, "rb");

	if (infile == NULL) {
		LOG(NULL, "Cannot read manifest", "%s (%s)\n", filename, strerror(errno));
		free(filename);
		return alloc_manifest(version, component);
	}

	/* line 1: MANIFEST\t<version> */
	line[0] = 0;
	if (fgets(line, 8191, infile) == NULL) {
		fclose(infile);
		return NULL;
	}

	if (strncmp(line, "MANIFEST\t", 9) != 0) {
		printf("Invalid file format: MANIFEST line\n");
		fclose(infile);
		return NULL;
	}
	c = &line[9];
	format_number = strtoull(c, NULL, 10);
	if ((errno < 0) || (format_number == 0)) {
		//format string shall be a positive integer
		printf("Unknown file format version in MANIFEST line: %s\n", c);
		fclose(infile);
		return NULL;
	}
	line[0] = 0;
	while (strcmp(line, "\n") != 0) {
		/* read the header */
		line[0] = 0;
		if (fgets(line, 8191, infile) == NULL) {
			break;
		}
		c = strchr(line, '\n');
		if (c) {
			*c = 0;
		}
		if (strlen(line) == 0) {
			break;
		}
		c = strchr(line, '\t');
		/* Make sure we're not at the end of the array before incrementing */
		if (c && c <= &line[strlen(line)]) {
			c++;
		} else {
			printf("Manifest is corrupt\n");
			assert(0);
		}

		if (strncmp(line, "version:", 8) == 0) {
			version = strtoull(c, NULL, 10);
		}
		if (strncmp(line, "previous:", 9) == 0) {
			previous = strtoull(c, NULL, 10);
		}
		if (strncmp(line, "includes:", 9) == 0) {
			includes = g_list_prepend(includes, strdup(c));
			if (!includes->data) {
				abort();
			}
		}
	}

	manifest = alloc_manifest(version, component);
	manifest->format = format_number;
	manifest->prevversion = previous;
	manifest->includes = includes;

	/* empty line */
	while (!feof(infile)) {
		struct file *file;

		line[0] = 0;
		if (fgets(line, 8191, infile) == NULL) {
			break;
		}
		c = strchr(line, '\n');
		if (c) {
			*c = 0;
		}
		if (strlen(line) == 0) {
			break;
		}

		file = calloc(1, sizeof(struct file));
		if (file == NULL) {
			assert(0);
		}
		c = line;

		c2 = strchr(c, '\t');
		if (c2) {
			*c2 = 0;
			c2++;
		}

		if (c[0] == 'F') {
			file->is_file = 1;
		} else if (c[0] == 'D') {
			file->is_dir = 1;
		} else if (c[0] == 'L') {
			file->is_link = 1;
		} else if (c[0] == 'M') {
			LOG(NULL, "Found a manifest!", "%s", c);
			file->is_manifest = 1;
		} else if (c[0] != '.') {
			assert(0); /* unknown file type */
		}

		if (c[1] == 'd') {
			file->is_deleted = 1;
		} else if (c[1] != '.') {
			assert(0); /* unknown deleted status */
		}

		if (c[2] == 'C') {
			file->is_config = 1;
		} else if (c[2] == 's') {
			file->is_state = 1;
		} else if (c[2] == 'b') {
			file->is_boot = 1;
		} else if (c[2] != '.') {
			assert(0); /* unknown modifier status */
		}

		if (c[3] == 'r') {
			file->is_rename = 1;
		} else if (c[3] != '.') {
			; /* field 4: ignore unknown letters */
		}

		c = c2;
		if (!c) {
			free(file);
			continue;
		}
		c2 = strchr(c, '\t');
		if (c2) {
			*c2 = 0;
			c2++;
		}

		hash_assign(c, file->hash);

		c = c2;
		if (!c) {
			free(file);
			continue;
		}
		c2 = strchr(c, '\t');
		if (c2) {
			*c2 = 0;
			c2++;
		}

		file->last_change = strtoull(c, NULL, 10);

		c = c2;
		if (!c) {
			free(file);
			continue;
		}
		file->filename = strdup(c);

		if (file->is_manifest) {
			nest_manifest_file(manifest, file);
		} else {
			manifest->files = g_list_prepend(manifest->files, file);
		}
		manifest->count++;
		count++;
	}

	manifest->files = g_list_sort(manifest->files, file_sort_filename);
	fclose(infile);
	LOG(NULL, "Manifest info", "Manifest for version %i/%s contains %i files", version, component, count);
	free(filename);
	return manifest;
}