static int rsa_verify_cert_cb(int fd, void *ud) { struct rsa_verify_cbdata *cbdata = ud; char *sha256; char *hash; char errbuf[1024]; RSA *rsa = NULL; int ret; sha256 = pkg_checksum_fd(fd, PKG_HASH_TYPE_SHA256_HEX); if (sha256 == NULL) return (EPKG_FATAL); hash = pkg_checksum_data(sha256, strlen(sha256), PKG_HASH_TYPE_SHA256_RAW); free(sha256); rsa = _load_rsa_public_key_buf(cbdata->key, cbdata->keylen); if (rsa == NULL) { free(hash); return (EPKG_FATAL); } ret = RSA_verify(NID_sha256, hash, pkg_checksum_type_size(PKG_HASH_TYPE_SHA256_RAW), cbdata->sig, cbdata->siglen, rsa); free(hash); if (ret == 0) { pkg_emit_error("rsa verify failed: %s", ERR_error_string(ERR_get_error(), errbuf)); RSA_free(rsa); return (EPKG_FATAL); } RSA_free(rsa); return (EPKG_OK); }
static void attempt_to_merge(bool renamed, struct pkg_config_file *rcf, struct pkg *local, char *pathname, const char *path, struct sbuf *newconf) { const struct pkg_file *lf = NULL; struct pkg_config_file *lcf = NULL; char *localconf = NULL; size_t sz; char *localsum; if (!renamed) { pkg_debug(3, "Not renamed"); return; } if (rcf == NULL) { pkg_debug(3, "No remote config file"); return; } if (local == NULL) { pkg_debug(3, "No local package"); return; } if (!pkg_is_config_file(local, path, &lf, &lcf)) { pkg_debug(3, "No local package"); return; } if (lcf->content == NULL) { pkg_debug(3, "Empty configuration content for local package"); return; } pkg_debug(1, "Config file found %s", pathname); file_to_buffer(pathname, &localconf, &sz); pkg_debug(2, "size: %d vs %d", sz, strlen(lcf->content)); if (sz == strlen(lcf->content)) { pkg_debug(2, "Ancient vanilla and deployed conf are the same size testing checksum"); localsum = pkg_checksum_data(localconf, sz, PKG_HASH_TYPE_SHA256_HEX); if (localsum && strcmp(localsum, lf->sum) == 0) { pkg_debug(2, "Checksum are the same %d", strlen(localconf)); free(localconf); free(localsum); return; } free(localsum); pkg_debug(2, "Checksum are different %d", strlen(localconf)); } pkg_debug(1, "Attempting to merge %s", pathname); if (merge_3way(lcf->content, localconf, rcf->content, newconf) != 0) { pkg_emit_error("Impossible to merge configuration file"); sbuf_clear(newconf); strlcat(pathname, ".pkgnew", MAXPATHLEN); } free(localconf); }
static bool pkg_repo_check_fingerprint(struct pkg_repo *repo, struct sig_cert *sc, bool fatal) { struct fingerprint *f = NULL; char *hash; int nbgood = 0; struct sig_cert *s = NULL, *stmp = NULL; struct pkg_repo_meta_key *mk = NULL; if (HASH_COUNT(sc) == 0) { if (fatal) pkg_emit_error("No signature found"); return (false); } /* load fingerprints */ if (repo->trusted_fp == NULL) { if (pkg_repo_load_fingerprints(repo) != EPKG_OK) return (false); } HASH_ITER(hh, sc, s, stmp) { if (s->sig != NULL && s->cert == NULL) { /* * We may want to check meta */ if (repo->meta != NULL && repo->meta->keys != NULL) HASH_FIND_STR(repo->meta->keys, s->name, mk); if (mk != NULL && mk->pubkey != NULL) { s->cert = mk->pubkey; s->certlen = strlen(mk->pubkey); } else { if (fatal) pkg_emit_error("No key with name %s has been found", s->name); return (false); } } else if (s->sig == NULL) { if (fatal) pkg_emit_error("No signature with name %s has been found", s->name); return (false); } s->trusted = false; hash = pkg_checksum_data(s->cert, s->certlen, PKG_HASH_TYPE_SHA256_HEX); HASH_FIND_STR(repo->revoked_fp, hash, f); if (f != NULL) { if (fatal) pkg_emit_error("At least one of the " "certificates has been revoked"); free(hash); return (false); } HASH_FIND_STR(repo->trusted_fp, hash, f); free(hash); if (f != NULL) { nbgood++; s->trusted = true; } } if (nbgood == 0) { if (fatal) pkg_emit_error("No trusted public keys found"); return (false); } return (true); }
static void attempt_to_merge(int rootfd, struct pkg_config_file *rcf, struct pkg *local, bool merge) { const struct pkg_file *lf = NULL; struct sbuf *newconf; struct pkg_config_file *lcf = NULL; char *localconf = NULL; off_t sz; char *localsum; if (rcf == NULL) { pkg_debug(3, "No remote config file"); return; } if (local == NULL) { pkg_debug(3, "No local package"); return; } if (!pkg_is_config_file(local, rcf->path, &lf, &lcf)) { pkg_debug(3, "No local package"); return; } if (lcf->content == NULL) { pkg_debug(3, "Empty configuration content for local package"); return; } pkg_debug(1, "Config file found %s", rcf->path); if (file_to_bufferat(rootfd, RELATIVE_PATH(rcf->path), &localconf, &sz) != EPKG_OK) return; pkg_debug(2, "size: %d vs %d", sz, strlen(lcf->content)); if (sz == strlen(lcf->content)) { pkg_debug(2, "Ancient vanilla and deployed conf are the same size testing checksum"); localsum = pkg_checksum_data(localconf, sz, PKG_HASH_TYPE_SHA256_HEX); if (localsum && strcmp(localsum, lf->sum) == 0) { pkg_debug(2, "Checksum are the same %d", strlen(localconf)); free(localconf); free(localsum); return; } free(localsum); pkg_debug(2, "Checksum are different %d", strlen(localconf)); } rcf->status = MERGE_FAILED; if (!merge) { free(localconf); return; } pkg_debug(1, "Attempting to merge %s", rcf->path); newconf = sbuf_new_auto(); if (merge_3way(lcf->content, localconf, rcf->content, newconf) != 0) { pkg_emit_error("Impossible to merge configuration file"); } else { sbuf_finish(newconf); rcf->newcontent = strdup(sbuf_data(newconf)); rcf->status = MERGE_SUCCESS; } sbuf_delete(newconf); free(localconf); }