static void verify_signature_pkcs7(const char *input) { #ifdef HAVE_SSL const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig; if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { begin_pkgvul = input + strlen(pgp_msg_start); if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL) errx(EXIT_FAILURE, "Invalid PGP signature"); if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL) errx(EXIT_FAILURE, "No PKCS7 signature"); } else { begin_pkgvul = input; if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL) errx(EXIT_FAILURE, "No PKCS7 signature"); end_pkgvul = begin_sig; } if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL) errx(EXIT_FAILURE, "Invalid PKCS7 signature"); end_sig += strlen(pkcs7_end); if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul, begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0)) errx(EXIT_FAILURE, "Unable to verify PKCS7 signature"); #else errx(EXIT_FAILURE, "OpenSSL support is not compiled in"); #endif }
int pkg_verify_signature(const char *archive_name, struct archive **archive, struct archive_entry **entry, char **pkgname) { struct signature_archive *state; struct archive_entry *my_entry; struct archive *a; char *hash_file, *signature_file; size_t hash_len, signature_len; int r, has_sig; *pkgname = NULL; state = xmalloc(sizeof(*state)); state->sign_blocks = NULL; state->sign_buf = NULL; state->archive = NULL; r = read_file_from_archive(archive_name, *archive, entry, HASH_FNAME, &hash_file, &hash_len); if (r == -1) { archive_read_finish(*archive); *archive = NULL; free(state); goto no_valid_signature; } else if (r == 1) { free(state); goto no_valid_signature; } if (parse_hash_file(hash_file, pkgname, state)) goto no_valid_signature; r = read_file_from_archive(archive_name, *archive, entry, SIGNATURE_FNAME, &signature_file, &signature_len); if (r == -1) { archive_read_finish(*archive); *archive = NULL; free(state); free(hash_file); goto no_valid_signature; } else if (r != 0) { if (*entry != NULL) r = read_file_from_archive(archive_name, *archive, entry, GPG_SIGNATURE_FNAME, &signature_file, &signature_len); if (r == -1) { archive_read_finish(*archive); *archive = NULL; free(state); free(hash_file); goto no_valid_signature; } else if (r != 0) { free(hash_file); free(state); goto no_valid_signature; } has_sig = !detached_gpg_verify(hash_file, hash_len, signature_file, signature_len, gpg_keyring_verify); free(signature_file); } else { #ifdef HAVE_SSL has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file, signature_len, certs_packages, 1); free(signature_file); #else warnx("No OpenSSL support compiled in, skipping signature"); has_sig = 0; free(signature_file); #endif } r = archive_read_next_header(*archive, &my_entry); if (r != ARCHIVE_OK) { warnx("Cannot read inner package: %s", archive_error_string(*archive)); free_signature_int(state); goto no_valid_signature; } if (archive_entry_size(my_entry) != state->pkg_size) { warnx("Package size doesn't match signature"); free_signature_int(state); goto no_valid_signature; } state->archive = *archive; a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_all(a); if (archive_read_open(a, state, NULL, verify_signature_read_cb, verify_signature_close_cb)) { warnx("Can't open signed package file"); archive_read_finish(a); goto no_valid_signature; } *archive = a; *entry = NULL; return has_sig ? 0 : -1; no_valid_signature: return -1; }