rpm  5.4.4
rpmdb/rpmns.c
Go to the documentation of this file.
00001 
00004 #include "system.h"
00005 
00006 #define _RPMIOB_INTERNAL        /* XXX rpmiobSlurp */
00007 #include <rpmiotypes.h>
00008 #include <rpmio.h>
00009 #define _RPMHKP_INTERNAL
00010 #include <rpmhkp.h>
00011 #include <rpmmacro.h>
00012 #include <rpmcb.h>
00013 
00014 #define _RPMPGP_INTERNAL
00015 #include <rpmpgp.h>
00016 
00017 #include <rpmtypes.h>
00018 #include <rpmtag.h>
00019 #define _RPMEVR_INTERNAL
00020 #include <rpmevr.h>
00021 #define _RPMNS_INTERNAL
00022 #include <rpmns.h>
00023 #include <rpmdb.h>
00024 
00025 #include <rpmps.h>
00026 #define _RPMTS_INTERNAL         /* XXX ts->hkp */
00027 #include <rpmts.h>
00028 
00029 #include "debug.h"
00030 
00031 /*@access rpmts @*/
00032 /*@access pgpDigParams @*/
00033 /*@access rpmiob @*/
00034 
00035 /*@unchecked@*/
00036 int _rpmns_debug = 0;
00037 
00038 /*@unchecked@*/ /*@observer@*/ /*@relnull@*/
00039 const char *_rpmns_N_at_A = ".";
00040 
00041 /*@-nullassign@*/
00042 /*@unchecked@*/ /*@observer@*/
00043 static const char *rpmnsArches[] = {
00044     "i386", "i486", "i586", "i686", "athlon", "pentium3", "pentium4",
00045     "x86_64", "amd64", "ia32e",
00046     "alpha", "alphaev5", "alphaev56", "alphapca56", "alphaev6", "alphaev67",
00047     "sparc", "sun4", "sun4m", "sun4c", "sun4d", "sparcv8",
00048     "sparcv9", "sparcv9b", "sparcv9v", "sparcv9v2",
00049     "sparc64", "sun4u", "sparc64v",
00050     "mips", "mipsel", "IP",
00051     "ppc", "ppciseries", "ppcpseries",
00052     "ppc64", "ppc64iseries", "ppc64pseries",
00053     "m68k",
00054     "rs6000",
00055     "ia64",
00056     "armv3l", "armv4b", "armv4l",
00057     "armv5teb", "armv5tel", "armv5tejl",
00058     "armv6l",
00059     "s390", "i370", "s390x",
00060     "sh", "sh3", "sh4", "sh4a", "xtensa",
00061     "noarch", "fat",
00062     NULL,
00063 };
00064 /*@=nullassign@*/
00065 
00066 nsType rpmnsArch(const char * str)
00067 {
00068     nsType rc = RPMNS_TYPE_UNKNOWN;
00069     const char ** av;
00070 
00071 #if defined(RPM_VENDOR_WINDRIVER)
00072     const char * known_arch = rpmExpand("%{?_known_arch}", NULL);
00073     const char *p, *pe, *t;
00074     for (p = pe = known_arch ; rc == RPMNS_TYPE_UNKNOWN && pe && *pe ; ) {
00075         while (*p && xisspace(*p)) p++;
00076         pe = p ; while (*pe && !xisspace(*pe)) pe++;
00077         if (p == pe)
00078             break;
00079         t = strndup(p, (pe - p));
00080         p = pe;
00081         if (!strcmp(str, t))
00082             rc = RPMNS_TYPE_ARCH;
00083         t = _free(t);
00084     }
00085     known_arch = _free(known_arch);
00086 #endif
00087 
00088     if (rc == RPMNS_TYPE_UNKNOWN)
00089     for (av = rpmnsArches; *av != NULL; av++) {
00090         if (strcmp(str, *av))
00091             continue;
00092         rc = RPMNS_TYPE_ARCH;
00093         break;
00094     }
00095 
00096     return rc;
00097 }
00098 
00102 /*@unchecked@*/ /*@observer@*/
00103 #define _ENTRY(_s, _type)       { #_s, sizeof(#_s)-1, _type }
00104 static struct _rpmnsProbes_s {
00105 /*@observer@*/ /*@relnull@*/
00106     const char * NS;
00107     size_t NSlen;
00108     nsType Type;
00109 } rpmnsProbes[] = {
00110     _ENTRY(RWX,         RPMNS_TYPE_ACCESS),
00111     _ENTRY(RW_,         RPMNS_TYPE_ACCESS),
00112     _ENTRY(RWx,         RPMNS_TYPE_ACCESS),
00113     _ENTRY(R_X,         RPMNS_TYPE_ACCESS),
00114     _ENTRY(R__,         RPMNS_TYPE_ACCESS),
00115     _ENTRY(R_x,         RPMNS_TYPE_ACCESS),
00116     _ENTRY(RwX,         RPMNS_TYPE_ACCESS),
00117     _ENTRY(Rw_,         RPMNS_TYPE_ACCESS),
00118     _ENTRY(Rwx,         RPMNS_TYPE_ACCESS),
00119     _ENTRY(_WX,         RPMNS_TYPE_ACCESS),
00120     _ENTRY(_W_,         RPMNS_TYPE_ACCESS),
00121     _ENTRY(_Wx,         RPMNS_TYPE_ACCESS),
00122     _ENTRY(__X,         RPMNS_TYPE_ACCESS),
00123     _ENTRY(___,         RPMNS_TYPE_ACCESS),
00124     _ENTRY(__x,         RPMNS_TYPE_ACCESS),
00125     _ENTRY(_wX,         RPMNS_TYPE_ACCESS),
00126     _ENTRY(_w_,         RPMNS_TYPE_ACCESS),
00127     _ENTRY(_wx,         RPMNS_TYPE_ACCESS),
00128     _ENTRY(config,      RPMNS_TYPE_CONFIG),
00129     _ENTRY(cpuinfo,     RPMNS_TYPE_CPUINFO),
00130     _ENTRY(digest,      RPMNS_TYPE_DIGEST),
00131     _ENTRY(diskspace,   RPMNS_TYPE_DISKSPACE),
00132     _ENTRY(envvar,      RPMNS_TYPE_ENVVAR),
00133     _ENTRY(executable,  RPMNS_TYPE_ACCESS),
00134     _ENTRY(exists,      RPMNS_TYPE_ACCESS),
00135     _ENTRY(getconf,     RPMNS_TYPE_GETCONF),
00136     _ENTRY(gnupg,       RPMNS_TYPE_GNUPG),
00137     _ENTRY(group,       RPMNS_TYPE_GROUP),
00138     _ENTRY(macro,       RPMNS_TYPE_MACRO),
00139     _ENTRY(mounted,     RPMNS_TYPE_MOUNTED),
00140     _ENTRY(rWX,         RPMNS_TYPE_ACCESS),
00141     _ENTRY(rW_,         RPMNS_TYPE_ACCESS),
00142     _ENTRY(rWx,         RPMNS_TYPE_ACCESS),
00143     _ENTRY(r_X,         RPMNS_TYPE_ACCESS),
00144     _ENTRY(r__,         RPMNS_TYPE_ACCESS),
00145     _ENTRY(r_x,         RPMNS_TYPE_ACCESS),
00146     _ENTRY(readable,    RPMNS_TYPE_ACCESS),
00147     _ENTRY(rpmlib,      RPMNS_TYPE_RPMLIB),
00148     _ENTRY(running,     RPMNS_TYPE_RUNNING),
00149     _ENTRY(rwX,         RPMNS_TYPE_ACCESS),
00150     _ENTRY(rw_,         RPMNS_TYPE_ACCESS),
00151     _ENTRY(rwx,         RPMNS_TYPE_ACCESS),
00152     _ENTRY(sanitycheck, RPMNS_TYPE_SANITY),
00153     _ENTRY(signature,   RPMNS_TYPE_SIGNATURE),
00154     _ENTRY(soname,      RPMNS_TYPE_SONAME),
00155     _ENTRY(uname,       RPMNS_TYPE_UNAME),
00156     _ENTRY(user,        RPMNS_TYPE_USER),
00157     _ENTRY(vcheck,      RPMNS_TYPE_VCHECK),
00158     _ENTRY(verify,      RPMNS_TYPE_VERIFY),
00159     _ENTRY(writable,    RPMNS_TYPE_ACCESS),
00160 };
00161 #undef  _ENTRY
00162 static size_t rpmnsProbesCount = sizeof(rpmnsProbes)/sizeof(rpmnsProbes[0]); 
00163 
00164 nsType rpmnsProbe(const char * s, size_t slen)
00165 {
00166     const char * se = strchr(s, ')');
00167     size_t l, u;
00168 
00169     /* XXX Don't bother if string cannot be "NS(N).A" */
00170     if (se == NULL || (slen = (se - s)) < sizeof("ABC()")-1)
00171         return RPMNS_TYPE_UNKNOWN;
00172 
00173     l = 0;
00174     u = rpmnsProbesCount;
00175     while (l < u) {
00176         size_t i = (l + u)/2;
00177         struct _rpmnsProbes_s * av = rpmnsProbes + i;
00178         size_t NSlen = (slen > av->NSlen) ? av->NSlen : slen;
00179         int rc = strncmp(s, av->NS, NSlen);
00180 
00181         if (rc == 0)
00182             return (s[NSlen] == '(' ? rpmnsProbes[i].Type : RPMNS_TYPE_UNKNOWN);
00183         else if (rc < 0)
00184             u = i;
00185         else if (rc > 0)
00186             l = i + 1;
00187     }
00188     return RPMNS_TYPE_UNKNOWN;
00189 }
00190 
00191 nsType rpmnsClassify(const char * s, size_t slen)
00192 {
00193     const char * se;
00194     nsType Type;
00195 
00196     if (slen == 0) slen = strlen(s);
00197     if (*s == '!') {
00198         s++;
00199         slen--;
00200     }
00201     if (*s == '/')
00202         return RPMNS_TYPE_PATH;
00203     se = s + slen;
00204     if (s[0] == '%' && s[1] == '{' && se[-1] == '}')
00205         return RPMNS_TYPE_FUNCTION;
00206     if ((se - s) > 3 && se[-3] == '.' && se[-2] == 's' && se[-1] == 'o')
00207         return RPMNS_TYPE_DSO;
00208     Type = rpmnsProbe(s, slen);
00209     if (Type != RPMNS_TYPE_UNKNOWN)
00210         return Type;
00211     for (se = s; *se != '\0'; se++) {
00212         if (se[0] == '(' || se[--slen] == ')')
00213             return RPMNS_TYPE_NAMESPACE;
00214         if (se[0] == '.' && se[1] == 's' && se[2] == 'o')
00215             return RPMNS_TYPE_DSO;
00216         if (se[0] == '.' && xisdigit((int)se[-1]) && xisdigit((int)se[1]))
00217             return RPMNS_TYPE_VERSION;
00218         if (_rpmns_N_at_A && _rpmns_N_at_A[0]) {
00219             if (se[0] == _rpmns_N_at_A[0] && rpmnsArch(se+1))
00220                 return RPMNS_TYPE_ARCH;
00221         }
00222 /*@-globstate@*/
00223         if (se[0] == '.')
00224             return RPMNS_TYPE_COMPOUND;
00225     }
00226     return RPMNS_TYPE_STRING;
00227 /*@=globstate@*/
00228 }
00229 
00230 int rpmnsParse(const char * s, rpmns ns)
00231 {
00232     char * t = rpmExpand(s, NULL);
00233     size_t tlen = strlen(t);
00234 
00235     ns->Flags = 0;
00236     ns->str = t;
00237     ns->Type = rpmnsClassify(t, tlen);
00238 
00239     switch (ns->Type) {
00240     case RPMNS_TYPE_ARCH:
00241         ns->NS = NULL;
00242         ns->N = ns->str;
00243         if (ns->N[0] == '!')
00244             ns->N++;
00245         if ((t = strrchr(t, _rpmns_N_at_A[0])) != NULL)
00246             *t++ = '\0';
00247         ns->A = t;
00248         break;
00249     case RPMNS_TYPE_RPMLIB:
00250     case RPMNS_TYPE_CPUINFO:
00251     case RPMNS_TYPE_GETCONF:
00252     case RPMNS_TYPE_UNAME:
00253     case RPMNS_TYPE_SONAME:
00254     case RPMNS_TYPE_ACCESS:
00255     case RPMNS_TYPE_USER:
00256     case RPMNS_TYPE_GROUP:
00257     case RPMNS_TYPE_MOUNTED:
00258     case RPMNS_TYPE_DISKSPACE:
00259     case RPMNS_TYPE_DIGEST:
00260     case RPMNS_TYPE_GNUPG:
00261     case RPMNS_TYPE_MACRO:
00262     case RPMNS_TYPE_ENVVAR:
00263     case RPMNS_TYPE_RUNNING:
00264     case RPMNS_TYPE_SANITY:
00265     case RPMNS_TYPE_VCHECK:
00266     case RPMNS_TYPE_SIGNATURE:
00267     case RPMNS_TYPE_VERIFY:
00268         ns->NS = ns->str;
00269         if (ns->NS[0] == '!')
00270             ns->NS++;
00271         if ((t = strchr(t, '(')) != NULL) {
00272             *t++ = '\0';
00273             ns->N = t;
00274             t[strlen(t)-1] = '\0';
00275         } else
00276            ns->N = NULL;
00277         ns->A = NULL;
00278         break;
00279     case RPMNS_TYPE_UNKNOWN:
00280     case RPMNS_TYPE_STRING:
00281     case RPMNS_TYPE_PATH:
00282     case RPMNS_TYPE_DSO:
00283     case RPMNS_TYPE_FUNCTION:
00284     case RPMNS_TYPE_VERSION:
00285     case RPMNS_TYPE_COMPOUND:
00286     case RPMNS_TYPE_NAMESPACE:
00287     case RPMNS_TYPE_TAG:
00288     case RPMNS_TYPE_CONFIG:
00289     default:
00290         ns->NS = NULL;
00291         ns->N = ns->str;
00292         if (ns->N[0] == '!')
00293             ns->N++;
00294         ns->A = NULL;
00295         break;
00296     }
00297     return 0;
00298 }
00299 
00305 static inline unsigned char nibble(char c)
00306         /*@*/
00307 {
00308     if (c >= '0' && c <= '9')
00309         return (unsigned char)(c - '0');
00310     if (c >= 'A' && c <= 'F')
00311         return (unsigned char)((int)(c - 'A') + 10);
00312     if (c >= 'a' && c <= 'f')
00313         return (unsigned char)((int)(c - 'a') + 10);
00314     return '\0';
00315 }
00316 
00317 rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
00318                 const char * pubfn, const char * pubid,
00319                 /*@unused@*/ int flags)
00320 {
00321     rpmts ts = _ts;
00322     pgpDig dig = rpmtsDig(ts);
00323     pgpDigParams sigp = pgpGetSignature(dig);
00324     pgpDigParams pubp = pgpGetPubkey(dig);
00325     rpmuint8_t * sigpkt = NULL;
00326     size_t sigpktlen = 0;
00327     DIGEST_CTX ctx = NULL;
00328     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00329     int xx;
00330 rpmhkp hkp = NULL;
00331 pgpPkt pp = alloca(sizeof(*pp));
00332 size_t pleft;
00333 int validate = 1;
00334 
00335 if (_rpmns_debug)
00336 fprintf(stderr, "==> check(%s, %s, %s, %s)\n", fn,
00337 (sigfn ? sigfn : "(null)"),
00338 (pubfn ? pubfn : "(null)"),
00339 (pubid ? pubid : "(null)"));
00340 
00341     /* Load the signature. Use sigfn if specified, otherwise clearsign. */
00342     if (sigfn && *sigfn) {
00343         const char * _sigfn = rpmExpand(sigfn, NULL);
00344         xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
00345         if (xx != PGPARMOR_SIGNATURE) {
00346 if (_rpmns_debug)
00347 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
00348             _sigfn = _free(_sigfn);
00349             goto exit;
00350         }
00351         _sigfn = _free(_sigfn);
00352     } else {
00353         const char * _sigfn = rpmExpand(fn, NULL);
00354         xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
00355         if (xx != PGPARMOR_SIGNATURE) {
00356 if (_rpmns_debug)
00357 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
00358             _sigfn = _free(_sigfn);
00359             goto exit;
00360         }
00361         _sigfn = _free(_sigfn);
00362     }
00363 
00364     pleft = sigpktlen;
00365     xx = pgpPktLen(sigpkt, pleft, pp);
00366     xx = rpmhkpLoadSignature(NULL, dig, pp);
00367     if (xx) goto exit;
00368 
00369     if (sigp->version != (rpmuint8_t)3 && sigp->version != (rpmuint8_t)4) {
00370 if (_rpmns_debug)
00371 fprintf(stderr, "==> unverifiable V%u\n", (unsigned)sigp->version);
00372         goto exit;
00373     }
00374 
00375     if (ts->hkp == NULL)
00376         ts->hkp = rpmhkpNew(NULL, 0);
00377     hkp = rpmhkpLink(ts->hkp);
00378 
00379     /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */
00380     if (pubfn && *pubfn) {
00381         const char * _pubfn = rpmExpand(pubfn, NULL);
00382 /*@-type@*/
00383 hkp->pkt = _free(hkp->pkt);     /* XXX memleaks */
00384 hkp->pktlen = 0;
00385         xx = pgpReadPkts(_pubfn, &hkp->pkt, &hkp->pktlen);
00386 /*@=type@*/
00387         if (xx != PGPARMOR_PUBKEY) {
00388 if (_rpmns_debug)
00389 fprintf(stderr, "==> pgpReadPkts(%s) PUB %p[%u] ret %d\n", _pubfn, hkp->pkt, (unsigned)hkp->pktlen, xx);
00390             _pubfn = _free(_pubfn);
00391             goto exit;
00392         }
00393         _pubfn = _free(_pubfn);
00394 
00395         /* Split the result into packet array. */
00396 hkp->pkts = _free(hkp->pkts);   /* XXX memleaks */
00397 hkp->npkts = 0;
00398         xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts);
00399 
00400         if (!xx)
00401             (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid);
00402         memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid));/* XXX useless */
00403 
00404         /* Validate pubkey self-signatures. */
00405         if (validate) {
00406             xx = rpmhkpValidate(hkp, NULL);
00407             switch (xx) {
00408             case RPMRC_OK:
00409                 break;
00410             case RPMRC_NOTFOUND:
00411             case RPMRC_FAIL:    /* XXX remap to NOTFOUND? */
00412             case RPMRC_NOTTRUSTED:
00413             case RPMRC_NOKEY:
00414             default:
00415                 rc = xx;
00416                 goto exit;
00417             }
00418         }
00419 
00420         /* Retrieve parameters from pubkey/subkey packet(s). */
00421         xx = rpmhkpFindKey(hkp, dig, sigp->signid, sigp->pubkey_algo);
00422         if (xx) goto exit;
00423 
00424 #ifdef  DYING
00425 _rpmhkpDumpDig(__FUNCTION__, dig);
00426 #endif
00427     } else {
00428         if ((rc = pgpFindPubkey(dig)) != RPMRC_OK) {
00429 if (_rpmns_debug)
00430 fprintf(stderr, "==> pgpFindPubkey ret %d\n", xx);
00431             goto exit;
00432         }
00433     }
00434 
00435     /* Is this the requested pubkey? */
00436     if (pubid && *pubid) {
00437         size_t ns = strlen(pubid);
00438         const char * s;
00439         char * t;
00440         size_t i;
00441 
00442         /* At least 8 hex digits please. */
00443         for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++)
00444             {};
00445         if (!(*s == '\0' && i > 8 && (i%2) == 0))
00446             goto exit;
00447 
00448         /* Truncate to key id size. */
00449         s = pubid;
00450         if (ns > 16) {
00451             s += (ns - 16);
00452             ns = 16;
00453         }
00454         ns >>= 1;
00455         t = memset(alloca(ns), 0, ns);
00456         for (i = 0; i < ns; i++)
00457             t[i] = (char)((nibble(s[2*i]) << 4) | nibble(s[2*i+1]));
00458 
00459         /* Compare the pubkey id. */
00460         s = (const char *)pubp->signid;
00461         xx = memcmp(t, s + (8 - ns), ns);
00462 
00463         /* XXX HACK: V4 RSA key id's are wonky atm. */
00464         if (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
00465             xx = 0;
00466 
00467         if (xx) {
00468 if (_rpmns_debug)
00469 fprintf(stderr, "==> mismatched: pubkey id (%08x %08x) != %s\n",
00470 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4), pubid);
00471             goto exit;
00472         }
00473     }
00474 
00475     /* Do the parameters match the signature? */
00476     if (!(sigp->pubkey_algo == pubp->pubkey_algo
00477 #ifdef  NOTYET
00478      && sigp->hash_algo == pubp->hash_algo
00479 #endif
00480     /* XXX HACK: V4 RSA key id's are wonky atm. */
00481      && (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA || !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid))) ) ) {
00482 if (_rpmns_debug) {
00483 fprintf(stderr, "==> mismatch between signature and pubkey\n");
00484 fprintf(stderr, "\tpubkey_algo: %u  %u\n", (unsigned)sigp->pubkey_algo, (unsigned)pubp->pubkey_algo);
00485 fprintf(stderr, "\tsignid: %08X %08X    %08X %08X\n",
00486 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4), 
00487 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4));
00488 }
00489         goto exit;
00490     }
00491 
00492     /* Compute the message digest. */
00493     ctx = rpmDigestInit((pgpHashAlgo)sigp->hash_algo, RPMDIGEST_NONE);
00494 
00495     {   
00496         static const char clrtxt[] = "-----BEGIN PGP SIGNED MESSAGE-----";
00497         static const char sigtxt[] = "-----BEGIN PGP SIGNATURE-----";
00498         const char * _fn = rpmExpand(fn, NULL);
00499         rpmiob iob = NULL;
00500         int _rc = rpmiobSlurp(_fn, &iob);
00501 
00502         if (!(_rc == 0 && iob != NULL)) {
00503 if (_rpmns_debug)
00504 fprintf(stderr, "==> rpmiobSlurp(%s) MSG ret %d\n", _fn, _rc);
00505             iob = rpmiobFree(iob);
00506             _fn = _free(_fn);
00507             goto exit;
00508         }
00509         _fn = _free(_fn);
00510 
00511         /* XXX clearsign sig is PGPSIGTYPE_TEXT not PGPSIGTYPE_BINARY. */
00512         if (!strncmp((char *)iob->b, clrtxt, strlen(clrtxt))) {
00513             const char * be = (char *) (iob->b + iob->blen);
00514             const char * t;
00515 
00516             /* Skip to '\n\n' start-of-plaintext */
00517             t = (char *) iob->b;
00518             while (t && t < be && *t != '\n')
00519                 t = strchr(t, '\n') + 1;
00520             if (!(t && t < be))
00521                 goto exit;
00522             t++;
00523 
00524             /* Clearsign digest rtrims " \t\r\n", inserts "\r\n" inter-lines. */
00525             while (t < be) {
00526                 const char * teol;
00527                 const char * te;
00528                 if (strncmp(t, "- ", 2) == 0)
00529                         t += 2;
00530                 if ((teol = te = strchr(t, '\n')) == NULL)
00531                     break;
00532                 while (te > t && strchr(" \t\r\n", te[-1]))
00533                     te--;
00534                 xx = rpmDigestUpdate(ctx, t, (te - t));
00535                 if (!strncmp((t = teol + 1), sigtxt, strlen(sigtxt)))
00536                     break;
00537                 xx = rpmDigestUpdate(ctx, "\r\n", sizeof("\r\n")-1);
00538             }
00539         } else
00540             xx = rpmDigestUpdate(ctx, iob->b, iob->blen);
00541 
00542         iob = rpmiobFree(iob);
00543     }
00544 
00545     if (sigp->hash != NULL)
00546         xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
00547 
00548     if (sigp->version == (rpmuint8_t)4) {
00549         rpmuint8_t trailer[6];
00550         trailer[0] = sigp->version;
00551         trailer[1] = (rpmuint8_t)0xff;
00552         trailer[2] = (sigp->hashlen >> 24) & 0xff;
00553         trailer[3] = (sigp->hashlen >> 16) & 0xff;
00554         trailer[4] = (sigp->hashlen >>  8) & 0xff;
00555         trailer[5] = (sigp->hashlen      ) & 0xff;
00556         xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
00557     }
00558 
00559     /* Load the message digest. */
00560     switch(sigp->pubkey_algo) {
00561     default:
00562         rc = RPMRC_FAIL;
00563         break;
00564     case PGPPUBKEYALGO_DSA:
00565         rc = (pgpImplSetDSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
00566         break;
00567     case PGPPUBKEYALGO_RSA:
00568         rc = (pgpImplSetRSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
00569         break;
00570     }
00571     if (rc != RPMRC_OK) {
00572 if (_rpmns_debug)
00573 fprintf(stderr, "==> can't load pubkey_algo(%u)\n", (unsigned)sigp->pubkey_algo);
00574         goto exit;
00575     }
00576 
00577     /* Verify the signature. */
00578     switch(sigp->pubkey_algo) {
00579     default:
00580         rc = RPMRC_FAIL;
00581         break;
00582     case PGPPUBKEYALGO_RSA:
00583     case PGPPUBKEYALGO_DSA:
00584         rc = (pgpImplVerify(dig) ? RPMRC_OK : RPMRC_FAIL);
00585         break;
00586     }
00587 
00588 exit:
00589     sigpkt = _free(sigpkt);
00590     (void) rpmhkpFree(hkp);
00591     hkp = NULL;
00592 /*@-nullstate@*/
00593     rpmtsCleanDig(ts);
00594 /*@=nullstate@*/
00595 
00596 if (_rpmns_debug)
00597 fprintf(stderr, "============================ verify: %s\n",
00598         (rc == RPMRC_OK ? "OK" :
00599         (rc == RPMRC_NOKEY ? "NOKEY" :
00600         "FAIL")));
00601 
00602     return rc;
00603 }