static rpmRC verifyMD5Digest(rpmtd sigtd, DIGEST_CTX md5ctx, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ uint8_t * md5sum = NULL; size_t md5len = 0; char *md5; const char *title = _("MD5 digest:"); *msg = NULL; DIGEST_CTX ctx = rpmDigestDup(md5ctx); if (ctx == NULL) { rasprintf(msg, "%s %s\n", title, rpmSigString(res)); goto exit; } (void) rpmDigestFinal(ctx, (void **)&md5sum, &md5len, 0); md5 = pgpHexStr(md5sum, md5len); if (md5len != sigtd->count || memcmp(md5sum, sigtd->data, md5len)) { char *hex = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL); rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title, rpmSigString(res), hex, md5); free(hex); } else { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5); } free(md5); exit: md5sum = _free(md5sum); return res; }
const char * Fdescr(FD_t fd) { if (fd == NULL) return _("[none]"); /* Lazy lookup if description is not set (eg dupped fd) */ if (fd->descr == NULL) { int fdno = fd->fps->fdno; #if defined(__linux__) /* Grab the path from /proc if we can */ char *procpath = NULL; char buf[PATH_MAX]; ssize_t llen; rasprintf(&procpath, "/proc/self/fd/%d", fdno); llen = readlink(procpath, buf, sizeof(buf)-1); free(procpath); if (llen >= 1) { buf[llen] = '\0'; /* Real paths in /proc are always absolute */ if (buf[0] == '/') fd->descr = xstrdup(buf); else fd->descr = rstrscat(NULL, "[", buf, "]", NULL); } #endif /* Still no description, base it on fdno which is always there */ if (fd->descr == NULL) rasprintf(&(fd->descr), "[fd %d]", fdno); } return fd->descr; }
static rpmRC verifyDigest(rpmtd sigtd, DIGEST_CTX digctx, const char *title, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ char * dig = NULL; size_t diglen = 0; char *pkgdig = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL); DIGEST_CTX ctx = rpmDigestDup(digctx); if (rpmDigestFinal(ctx, (void **)&dig, &diglen, 1) || diglen == 0) { rasprintf(msg, "%s %s", title, rpmSigString(res)); goto exit; } if (strcasecmp(pkgdig, dig) == 0) { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)", title, rpmSigString(res), pkgdig); } else { rasprintf(msg, "%s: %s Expected(%s) != (%s)", title, rpmSigString(res), pkgdig, dig); } exit: free(dig); free(pkgdig); return res; }
/** * Check file info from header against what's actually installed. * @param ts transaction set * @param h header to verify * @param omitMask bits to disable verify checks * @param ghosts should ghosts be verified? * @return 0 no problems, 1 problems found */ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts) { rpmVerifyAttrs verifyResult = 0; int ec = 0; /* assume no problems */ rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY); rpmfiInit(fi, 0); while (rpmfiNext(fi) >= 0) { rpmfileAttrs fileAttrs = rpmfiFFlags(fi); char *buf = NULL, *attrFormat; char ac; int rc; /* If not verifying %ghost, skip ghost files. */ if ((fileAttrs & RPMFILE_GHOST) && !ghosts) continue; rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask); /* Filter out timestamp differences of shared files */ if (rc == 0 && (verifyResult & RPMVERIFY_MTIME)) { rpmdbMatchIterator mi; mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0); if (rpmdbGetIteratorCount(mi) > 1) verifyResult &= ~RPMVERIFY_MTIME; rpmdbFreeIterator(mi); } attrFormat = rpmFFlagsString(fileAttrs, ""); ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0]; if (rc) { if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) { rasprintf(&buf, _("missing %c %s"), ac, rpmfiFN(fi)); if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) { char *app; rasprintf(&app, " (%s)", strerror(errno)); rstrcat(&buf, app); free(app); } ec = rc; } } else if (verifyResult || rpmIsVerbose()) { char *verifyFormat = rpmVerifyString(verifyResult, "."); rasprintf(&buf, "%s %c %s", verifyFormat, ac, rpmfiFN(fi)); free(verifyFormat); if (verifyResult) ec = 1; } free(attrFormat); if (buf) { rpmlog(RPMLOG_NOTICE, "%s\n", buf); buf = _free(buf); } } rpmfiFree(fi); return ec; }
/** * Verify header immutable region SHA1 digest. * @retval msg verbose success/failure text * @param sha1ctx * @return RPMRC_OK on success */ static rpmRC verifySHA1Digest(rpmtd sigtd, DIGEST_CTX sha1ctx, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ char * SHA1 = NULL; const char *title = _("Header SHA1 digest:"); const char *sig = sigtd->data; *msg = NULL; DIGEST_CTX ctx = rpmDigestDup(sha1ctx); if (ctx == NULL) { rasprintf(msg, "%s %s\n", title, rpmSigString(res)); goto exit; } (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1); if (SHA1 == NULL || !rstreq(SHA1, sig)) { rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title, rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)"); } else { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1); } exit: SHA1 = _free(SHA1); return res; }
/** * Check for inappropriate characters. All alphanums are considered sane. * @param spec spec (or NULL) * @param field string to check * @param whitelist string of permitted characters * @return RPMRC_OK if OK */ rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist) { const char *ch; char *err = NULL; rpmRC rc = RPMRC_OK; for (ch=field; *ch; ch++) { if (risalnum(*ch) || strchr(whitelist, *ch)) continue; rasprintf(&err, _("Illegal char '%c' (0x%x)"), isprint(*ch) ? *ch : '?', *ch); } for (ch=field; *ch; ch++) { if (strchr("%{}", *ch)) { specLog(spec, RPMLOG_WARNING, field, _("Possible unexpanded macro")); break; } } if (err == NULL && strstr(field, "..") != NULL) { rasprintf(&err, _("Illegal sequence \"..\"")); } if (err) { specLog(spec, RPMLOG_ERR, field, err); free(err); rc = RPMRC_FAIL; } return rc; }
void platform_keyDirs(char*** path, size_t* len) { static const char suffix[] = "cbt"; static const char hidden_suffix[] = ".cbt"; static char *paths[NUM_PATHS]; *len = (NUM_PATHS - 1); *path = paths; paths[0] = rasprintf("%s/%s", getenv("HOME"), suffix); paths[1] = rasprintf("%s/%s", getenv("HOME"), hidden_suffix); }
char *rpmsinfoMsg(struct rpmsinfo_s *sinfo, rpmRC rc, const char *emsg) { char *msg = NULL; if (emsg) { rasprintf(&msg, "%s: %s (%s)", rpmsinfoDescr(sinfo), rpmSigString(rc), emsg); } else { rasprintf(&msg, "%s: %s", rpmsinfoDescr(sinfo), rpmSigString(rc)); } return msg; }
static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body, rpmscriptFlags flags) { char *nevra = headerGetAsString(h, RPMTAG_NEVRA); rpmScript script = xcalloc(1, sizeof(*script)); script->tag = tag; script->flags = flags; script->body = (body != NULL) ? xstrdup(body) : NULL; rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra); /* macros need to be expanded before possible queryformat */ if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) { char *body = rpmExpand(script->body, NULL); free(script->body); script->body = body; } if (script->body && (script->flags & RPMSCRIPT_FLAG_QFORMAT)) { /* XXX TODO: handle queryformat errors */ char *body = headerFormat(h, script->body, NULL); free(script->body); script->body = body; } free(nevra); return script; }
int urlGetFile(const char * url, const char * dest) { char *cmd = NULL; const char *target = NULL; char *urlhelper = NULL; int rc; pid_t pid, wait; urlhelper = rpmExpand("%{?_urlhelper}", NULL); if (dest == NULL) { urlPath(url, &target); } else { target = dest; } /* XXX TODO: sanity checks like target == dest... */ rasprintf(&cmd, "%s %s %s", urlhelper, target, url); urlhelper = _free(urlhelper); if ((pid = fork()) == 0) { ARGV_t argv = NULL; argvSplit(&argv, cmd, " "); execvp(argv[0], argv); exit(127); /* exit with 127 for compatibility with bash(1) */ } wait = waitpid(pid, &rc, 0); cmd = _free(cmd); return rc; }
static void printFileInfo(const char * name, rpm_loff_t size, unsigned short mode, unsigned int mtime, unsigned short rdev, unsigned int nlink, const char * owner, const char * group, const char * linkto) { char sizefield[21]; char ownerfield[8+1], groupfield[8+1]; char timefield[100]; time_t when = mtime; /* important if sizeof(int32_t) ! sizeof(time_t) */ struct tm * tm; static time_t now; char * perms = rpmPermsString(mode); char *link = NULL; /* On first call, grab snapshot of now */ if (now == 0) now = time(NULL); rstrlcpy(ownerfield, owner, sizeof(ownerfield)); rstrlcpy(groupfield, group, sizeof(groupfield)); /* this is normally right */ snprintf(sizefield, sizeof(sizefield), "%20" PRIu64, size); /* this knows too much about dev_t */ if (S_ISLNK(mode)) { rasprintf(&link, "%s -> %s", name, linkto); } else if (S_ISCHR(mode)) { perms[0] = 'c'; snprintf(sizefield, sizeof(sizefield), "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff), ((unsigned)rdev & 0xff)); } else if (S_ISBLK(mode)) {
static char * prDbiOpenFlags(int dbflags, int print_dbenv_flags) { ARGV_t flags = NULL; const struct poptOption *opt; char *buf; for (opt = rdbOptions; opt->longName != NULL; opt++) { if (opt->argInfo != POPT_BIT_SET) continue; if (print_dbenv_flags) { if (!(opt->arg == &staticcfg.db_eflags)) continue; } else { if (!(opt->arg == &staticdbicfg.dbi_oflags)) continue; } if ((dbflags & opt->val) != opt->val) continue; argvAdd(&flags, opt->longName); dbflags &= ~opt->val; } if (dbflags) { char *df = NULL; rasprintf(&df, "0x%x", (unsigned)dbflags); argvAdd(&flags, df); free(df); } buf = argvJoin(flags, ":"); argvFree(flags); return buf ? buf : xstrdup("(none)"); }
rpmRC rpmdsParseRichDep(rpmds dep, rpmds *leftds, rpmds *rightds, rpmrichOp *op, char **emsg) { rpmRC rc; struct rpmdsParseRichDepData data; const char *depstr = rpmdsN(dep); memset(&data, 0, sizeof(data)); data.dep = dep; data.op = RPMRICHOP_SINGLE; data.depflags = rpmdsFlags(dep) & ~(RPMSENSE_SENSEMASK | RPMSENSE_RICH | RPMSENSE_MISSINGOK); rc = rpmrichParse(&depstr, emsg, rpmdsParseRichDepCB, &data); if (rc == RPMRC_OK && *depstr) { if (emsg) rasprintf(emsg, _("Junk after rich dependency")); rc = RPMRC_FAIL; } if (rc != RPMRC_OK) { rpmdsFree(data.leftds); rpmdsFree(data.rightds); } else { *leftds = data.leftds; *rightds = data.rightds; *op = data.op; } return rc; }
int rpmPkgSign(const char *path, const struct rpmSignArgs * args) { int rc; if (args) { if (args->hashalgo) { char *algo = NULL; rasprintf(&algo, "%d", args->hashalgo); rpmPushMacro(NULL, "_gpg_digest_algo", NULL, algo, RMIL_GLOBAL); free(algo); } if (args->keyid) { rpmPushMacro(NULL, "_gpg_name", NULL, args->keyid, RMIL_GLOBAL); } } rc = rpmSign(path, 0, args ? args->signfiles : 0); if (args) { if (args->hashalgo) { rpmPopMacro(NULL, "_gpg_digest_algo"); } if (args->keyid) { rpmPopMacro(NULL, "_gpg_name"); } } return rc; }
rpmRC rpmLeadRead(FD_t fd, int *type, char **emsg) { rpmRC rc = RPMRC_OK; struct rpmlead_s l; char *err = NULL; memset(&l, 0, sizeof(l)); if (Freadall(fd, &l, sizeof(l)) != sizeof(l)) { if (Ferror(fd)) { rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno); rc = RPMRC_FAIL; } else { err = xstrdup(_("not an rpm package\n")); rc = RPMRC_NOTFOUND; } } else { l.type = ntohs(l.type); l.archnum = ntohs(l.archnum); l.osnum = ntohs(l.osnum); l.signature_type = ntohs(l.signature_type); rc = rpmLeadCheck(&l, &err); } if (rc == RPMRC_OK) { if (type != NULL) *type = l.type; } else { if (emsg != NULL) *emsg = err; else free(err); } return rc; }
/** * Return shell escape formatted data. * @param td tag data container * @return formatted string */ static char * shescapeFormat(rpmtd td) { char * result = NULL, * dst, * src; if (rpmtdClass(td) == RPM_NUMERIC_CLASS) { rasprintf(&result, "%" PRIu64, rpmtdGetNumber(td)); } else { char *buf = xstrdup(rpmtdGetString(td));; result = dst = xmalloc(strlen(buf) * 4 + 3); *dst++ = '\''; for (src = buf; *src != '\0'; src++) { if (*src == '\'') { *dst++ = '\''; *dst++ = '\\'; *dst++ = '\''; *dst++ = '\''; } else { *dst++ = *src; } } *dst++ = '\''; *dst = '\0'; free(buf); } return result; }
static rpmRC checkSep(const char *s, char c, char **emsg) { const char *sep = strchr(s, c); if (sep && strchr(sep + 1, c)) { rasprintf(emsg, "Invalid version (double separator '%c'): %s", c, s); } return RPMRC_OK; }
/** * Retrieve i18n text. * @param h header * @param tag tag * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int i18nTag(Header h, rpmTag tag, rpmtd td, headerGetFlags hgflags) { int rc; #if defined(ENABLE_NLS) char * dstring = rpmExpand(_macro_i18ndomains, NULL); td->type = RPM_STRING_TYPE; td->data = NULL; td->count = 0; if (dstring && *dstring) { char *domain, *de; const char * langval; char * msgkey; const char * msgid; rasprintf(&msgkey, "%s(%s)", headerGetString(h, RPMTAG_NAME), rpmTagGetName(tag)); /* change to en_US for msgkey -> msgid resolution */ langval = getenv(language); (void) setenv(language, "en_US", 1); ++_nl_msg_cat_cntr; msgid = NULL; for (domain = dstring; domain != NULL; domain = de) { de = strchr(domain, ':'); if (de) *de++ = '\0'; msgid = dgettext(domain, msgkey); if (msgid != msgkey) break; } /* restore previous environment for msgid -> msgstr resolution */ if (langval) (void) setenv(language, langval, 1); else unsetenv(language); ++_nl_msg_cat_cntr; if (domain && msgid) { td->data = dgettext(domain, msgid); td->data = xstrdup(td->data); /* XXX xstrdup has side effects. */ td->count = 1; td->flags = RPMTD_ALLOCED; } dstring = _free(dstring); free(msgkey); if (td->data) return 1; } free(dstring); #endif rc = headerGet(h, tag, td, HEADERGET_ALLOC); return rc; }
/** \ingroup rpmpgp * Return hex formatted representation of a multiprecision integer. * @param p bytes * @return hex formatted string (malloc'ed) */ static inline char * pgpMpiStr(const uint8_t *p) { char *str = NULL; char *hex = pgpHexStr(p+2, pgpMpiLen(p)-2); rasprintf(&str, "[%4u]: %s", pgpGrab(p, (size_t) 2), hex); free(hex); return str; }
int argvAddNum(ARGV_t *argvp, int val) { char *valstr = NULL; int rc; rasprintf(&valstr, "%d", val); rc = argvAdd(argvp, valstr); free(valstr); return rc; }
const char *rpmsinfoDescr(struct rpmsinfo_s *sinfo) { if (sinfo->descr == NULL) { char *t; switch (sinfo->type) { case RPMSIG_DIGEST_TYPE: rasprintf(&sinfo->descr, _("%s%s %s"), rangeName(sinfo->range), pgpValString(PGPVAL_HASHALGO, sinfo->hashalgo), _("digest")); break; case RPMSIG_SIGNATURE_TYPE: t = sinfo->sig ? pgpIdentItem(sinfo->sig) : NULL; rasprintf(&sinfo->descr, _("%s%s"), rangeName(sinfo->range), t ? t : _("signature")); free(t); break; } } return sinfo->descr; }
static char * numFormat(rpmtd td, const char *format) { char * val = NULL; if (rpmtdClass(td) != RPM_NUMERIC_CLASS) { val = xstrdup(_("(not a number)")); } else { rasprintf(&val, format, rpmtdGetNumber(td)); } return val; }
static int readFile(FD_t fd, char **msg) { unsigned char buf[4*BUFSIZ]; ssize_t count; /* Read the payload from the package. */ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {} if (count < 0) rasprintf(msg, _("Fread failed: %s"), Fstrerror(fd)); return (count != 0); }
/** * Verify DSA/RSA signature. * @param keyring pubkey keyring * @param sig OpenPGP signature parameters * @param hashctx digest context * @param isHdr header-only signature? * @retval msg verbose success/failure text * @return RPMRC_OK on success */ static rpmRC verifySignature(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX hashctx, int isHdr, char **msg) { rpmRC res = rpmKeyringVerifySig(keyring, sig, hashctx); char *sigid = pgpIdentItem(sig); rasprintf(msg, "%s%s: %s\n", isHdr ? _("Header ") : "", sigid, rpmSigString(res)); free(sigid); return res; }
static rpmRC parseSimpleDep(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata) { const char *p = *dstrp; const char *n, *e = 0; int nl, el = 0; rpmsenseFlags sense = 0; n = p; SKIPNONWHITEX(p); nl = p - n; if (nl == 0) { if (emsg) rasprintf(emsg, _("Name required")); return RPMRC_FAIL; } SKIPWHITE(p); if (*p) { const char *pe = p; SKIPNONWHITEX(pe); sense = rpmParseDSFlags(p, pe - p); if (sense) { p = pe; SKIPWHITE(p); e = p; SKIPNONWHITEX(p); el = p - e; } } if (e && el == 0) { if (emsg) rasprintf(emsg, _("Version required")); return RPMRC_FAIL; } if (cb(cbdata, RPMRICH_PARSE_SIMPLE, n, nl, e, el, sense, RPMRICHOP_SINGLE, emsg) != RPMRC_OK) return RPMRC_FAIL; *dstrp = p; return RPMRC_OK; }
static rpmRC checkDep(rpmSpec spec, char *N, char *EVR, char **emsg) { /* * Tokens must begin with alphanumeric, _, or /, but we don't know * the spec's encoding so we only check what we can: plain ascii. */ if (isascii(N[0]) && !(risalnum(N[0]) || N[0] == '_' || N[0] == '/')) { rasprintf(emsg, _("Dependency tokens must begin with alpha-numeric, '_' or '/'")); return RPMRC_FAIL; } if (EVR) { if (N[0] == '/') { rasprintf(emsg, _("Versioned file name not permitted")); return RPMRC_FAIL; } if (rpmCharCheck(spec, EVR, ".-_+:%{}~")) return RPMRC_FAIL; if (checkSep(EVR, '-', emsg) != RPMRC_OK || checkSep(EVR, ':', emsg) != RPMRC_OK) return RPMRC_FAIL; } return RPMRC_OK; }
/* * Format sigcheck result for output, appending the message spew to buf and * bad/missing keyids to keyprob. * * In verbose mode, just dump it all. Otherwise ok signatures * are dumped lowercase, bad sigs uppercase and for PGP/GPG * if misssing/untrusted key it's uppercase in parenthesis * and stash the key id as <SIGTYPE>#<keyid>. Pfft. */ static void formatResult(rpmTagVal sigtag, rpmRC sigres, const char *result, char **keyprob, char **buf) { char *msg = NULL; if (rpmIsVerbose()) { rasprintf(&msg, " %s\n", result); } else { /* Check for missing / untrusted keys in result. */ const char *signame = sigtagname(sigtag, (sigres != RPMRC_OK)); if (sigres == RPMRC_NOKEY || sigres == RPMRC_NOTTRUSTED) { const char *tempKey = strstr(result, "ey ID"); if (tempKey) { char keyid[sizeof(pgpKeyID_t) + 1]; rstrlcpy(keyid, tempKey + 6, sizeof(keyid)); rstrscat(keyprob, " ", signame, "#", keyid, NULL); } } rasprintf(&msg, (*keyprob ? "(%s) " : "%s "), signame); } rstrcat(buf, msg); free(msg); }
char * rpmFFlagsString(uint32_t fflags, const char *pad) { char *fmt = NULL; rasprintf(&fmt, "%s%s%s%s%s%s%s%s", (fflags & RPMFILE_DOC) ? "d" : pad, (fflags & RPMFILE_CONFIG) ? "c" : pad, (fflags & RPMFILE_SPECFILE) ? "s" : pad, (fflags & RPMFILE_MISSINGOK) ? "m" : pad, (fflags & RPMFILE_NOREPLACE) ? "n" : pad, (fflags & RPMFILE_GHOST) ? "g" : pad, (fflags & RPMFILE_LICENSE) ? "l" : pad, (fflags & RPMFILE_README) ? "r" : pad); return fmt; }
int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEVR) { char *reqname = NULL; int res; rasprintf(&reqname, "rpmlib(%s)", feature); res = addReqProv(pkg, RPMTAG_REQUIRENAME, reqname, featureEVR, RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL), 0); free(reqname); return res; }
static void addDep(ARGV_t *deps, const char *soname, const char *ver, const char *marker) { char *dep = NULL; if (skipSoname(soname)) return; if (ver || marker) { rasprintf(&dep, "%s(%s)%s", soname, ver ? ver : "", marker ? marker : ""); } argvAdd(deps, dep ? dep : soname); free(dep); }