Download checksums.txt and verify the archive integrity. Every non-zero * result is a fail-closed refusal; verification is never optional. */
| 7131 | /* Download checksums.txt and verify the archive integrity. Every non-zero |
| 7132 | * result is a fail-closed refusal; verification is never optional. */ |
| 7133 | static int verify_download_checksum(const char *archive_path, const char *archive_name) { |
| 7134 | char checksum_file[CLI_BUF_256]; |
| 7135 | int checksum_path_length = |
| 7136 | snprintf(checksum_file, sizeof(checksum_file), "%s/cbm-checksums-XXXXXX", cbm_tmpdir()); |
| 7137 | if (checksum_path_length <= 0 || (size_t)checksum_path_length >= sizeof(checksum_file)) { |
| 7138 | return CLI_ERR; |
| 7139 | } |
| 7140 | int checksum_descriptor = cbm_mkstemp(checksum_file); |
| 7141 | if (checksum_descriptor < 0) { |
| 7142 | return CLI_ERR; |
| 7143 | } |
| 7144 | #ifdef _WIN32 |
| 7145 | int checksum_close_status = _close(checksum_descriptor); |
| 7146 | #else |
| 7147 | int checksum_close_status = close(checksum_descriptor); |
| 7148 | #endif |
| 7149 | if (checksum_close_status != 0) { |
| 7150 | cbm_unlink(checksum_file); |
| 7151 | return CLI_ERR; |
| 7152 | } |
| 7153 | |
| 7154 | char dl_base_buf[CLI_BUF_512]; |
| 7155 | const char *dl_base = |
| 7156 | cbm_safe_getenv("CBM_DOWNLOAD_URL", dl_base_buf, sizeof(dl_base_buf), NULL); |
| 7157 | char checksum_url[CLI_BUF_512]; |
| 7158 | int checksum_url_length; |
| 7159 | if (dl_base && dl_base[0]) { |
| 7160 | checksum_url_length = |
| 7161 | snprintf(checksum_url, sizeof(checksum_url), "%s/checksums.txt", dl_base); |
| 7162 | } else { |
| 7163 | checksum_url_length = |
| 7164 | snprintf(checksum_url, sizeof(checksum_url), "%s", |
| 7165 | "https://github.com/DeusData/codebase-memory-mcp/releases/latest/" |
| 7166 | "download/checksums.txt"); |
| 7167 | } |
| 7168 | if (checksum_url_length <= 0 || (size_t)checksum_url_length >= sizeof(checksum_url)) { |
| 7169 | cbm_unlink(checksum_file); |
| 7170 | return CLI_ERR; |
| 7171 | } |
| 7172 | int rc = cbm_download_to_file_quiet(checksum_url, checksum_file); |
| 7173 | if (rc != 0) { |
| 7174 | (void)fprintf(stderr, "error: could not download checksums.txt for mandatory " |
| 7175 | "verification\n"); |
| 7176 | cbm_unlink(checksum_file); |
| 7177 | return CLI_ERR; |
| 7178 | } |
| 7179 | |
| 7180 | char expected[SHA256_BUF_SIZE] = {0}; |
| 7181 | int manifest_status = |
| 7182 | cbm_cli_checksum_manifest_digest(checksum_file, archive_name, expected, sizeof(expected)); |
| 7183 | cbm_unlink(checksum_file); |
| 7184 | if (manifest_status != CLI_OK) { |
| 7185 | (void)fprintf(stderr, |
| 7186 | "error: checksums.txt has no single valid SHA-256 entry " |
| 7187 | "for exact artifact %s\n", |
| 7188 | archive_name); |
| 7189 | return CLI_ERR; |
| 7190 | } |
no test coverage detected