tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

verify.c (9976B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "signtool.h"
      6 
      7 static int jar_cb(int status, JAR *jar, const char *metafile,
      8                  char *pathname, char *errortext);
      9 static int verify_global(JAR *jar);
     10 
     11 /*************************************************************************
     12 *
     13 * V e r i f y J a r
     14 */
     15 int
     16 VerifyJar(char *filename)
     17 {
     18    FILE *fp;
     19 
     20    int ret;
     21    int status;
     22    int failed = 0;
     23    char *err;
     24 
     25    JAR *jar;
     26    JAR_Context *ctx;
     27 
     28    JAR_Item *it;
     29 
     30    jar = JAR_new();
     31 
     32    if ((fp = fopen(filename, "r")) == NULL) {
     33        perror(filename);
     34        exit(ERRX);
     35    } else
     36        fclose(fp);
     37 
     38    JAR_set_callback(JAR_CB_SIGNAL, jar, jar_cb);
     39 
     40    status = JAR_pass_archive(jar, jarArchGuess, filename, "some-url");
     41 
     42    if (status < 0 || jar->valid < 0) {
     43        failed = 1;
     44        PR_fprintf(outputFD,
     45                   "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
     46                   filename);
     47        if (status < 0) {
     48            const char *errtext;
     49 
     50            if (status >= JAR_BASE && status <= JAR_BASE_END) {
     51                errtext = JAR_get_error(status);
     52            } else {
     53                errtext = SECU_Strerror(PORT_GetError());
     54            }
     55 
     56            PR_fprintf(outputFD, "  (reported reason: %s)\n\n",
     57                       errtext);
     58 
     59            /* corrupt files should not have their contents listed */
     60 
     61            if (status == JAR_ERR_CORRUPT)
     62                return -1;
     63        }
     64        PR_fprintf(outputFD,
     65                   "entries shown below will have their digests checked only.\n");
     66        jar->valid = 0;
     67    } else
     68        PR_fprintf(outputFD,
     69                   "archive \"%s\" has passed crypto verification.\n", filename);
     70 
     71    if (verify_global(jar))
     72        failed = 1;
     73 
     74    PR_fprintf(outputFD, "\n");
     75    PR_fprintf(outputFD, "%16s   %s\n", "status", "path");
     76    PR_fprintf(outputFD, "%16s   %s\n", "------------", "-------------------");
     77 
     78    ctx = JAR_find(jar, NULL, jarTypeMF);
     79 
     80    while (JAR_find_next(ctx, &it) >= 0) {
     81        if (it && it->pathname) {
     82            rm_dash_r(TMP_OUTPUT);
     83            ret = JAR_verified_extract(jar, it->pathname, TMP_OUTPUT);
     84            /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
     85            if (ret < 0)
     86                failed = 1;
     87 
     88            if (ret == JAR_ERR_PNF)
     89                err = "NOT PRESENT";
     90            else if (ret == JAR_ERR_HASH)
     91                err = "HASH FAILED";
     92            else
     93                err = "NOT VERIFIED";
     94 
     95            PR_fprintf(outputFD, "%16s   %s\n",
     96                       ret >= 0 ? "verified" : err, it->pathname);
     97 
     98            if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
     99                PR_fprintf(outputFD, "      (reason: %s)\n",
    100                           JAR_get_error(ret));
    101        }
    102    }
    103 
    104    JAR_find_end(ctx);
    105 
    106    if (status < 0 || jar->valid < 0) {
    107        failed = 1;
    108        PR_fprintf(outputFD,
    109                   "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
    110                   filename);
    111        give_help(status);
    112    }
    113 
    114    JAR_destroy(jar);
    115 
    116    if (failed)
    117        return -1;
    118    return 0;
    119 }
    120 
    121 /***************************************************************************
    122 *
    123 * v e r i f y _ g l o b a l
    124 */
    125 static int
    126 verify_global(JAR *jar)
    127 {
    128    FILE *fp;
    129    JAR_Context *ctx;
    130    JAR_Item *it;
    131    JAR_Digest *globaldig;
    132    char *ext;
    133    unsigned char *md5_digest, *sha1_digest;
    134    unsigned int sha1_length, md5_length;
    135    int retval = 0;
    136    char buf[BUFSIZ];
    137 
    138    ctx = JAR_find(jar, "*", jarTypePhy);
    139 
    140    while (JAR_find_next(ctx, &it) >= 0) {
    141        if (!PORT_Strncmp(it->pathname, "META-INF", 8)) {
    142            for (ext = it->pathname; *ext; ext++)
    143                ;
    144            while (ext > it->pathname && *ext != '.')
    145                ext--;
    146 
    147            if (verbosity >= 0) {
    148                if (!PORT_Strcasecmp(ext, ".rsa")) {
    149                    PR_fprintf(outputFD, "found a RSA signature file: %s\n",
    150                               it->pathname);
    151                }
    152 
    153                if (!PORT_Strcasecmp(ext, ".dsa")) {
    154                    PR_fprintf(outputFD, "found a DSA signature file: %s\n",
    155                               it->pathname);
    156                }
    157 
    158                if (!PORT_Strcasecmp(ext, ".mf")) {
    159                    PR_fprintf(outputFD,
    160                               "found a MF master manifest file: %s\n",
    161                               it->pathname);
    162                }
    163            }
    164 
    165            if (!PORT_Strcasecmp(ext, ".sf")) {
    166                if (verbosity >= 0) {
    167                    PR_fprintf(outputFD,
    168                               "found a SF signature manifest file: %s\n",
    169                               it->pathname);
    170                }
    171 
    172                rm_dash_r(TMP_OUTPUT);
    173                if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) {
    174                    PR_fprintf(errorFD, "%s: error extracting %s\n",
    175                               PROGRAM_NAME, it->pathname);
    176                    errorCount++;
    177                    retval = -1;
    178                    continue;
    179                }
    180 
    181                md5_digest = NULL;
    182                sha1_digest = NULL;
    183 
    184                if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) {
    185                    while (fgets(buf, BUFSIZ, fp)) {
    186                        char *s;
    187 
    188                        if (*buf == 0 || *buf == '\n' || *buf == '\r')
    189                            break;
    190 
    191                        for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
    192                            ;
    193                        *s = 0;
    194 
    195                        if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) {
    196                            md5_digest =
    197                                ATOB_AsciiToData(buf + 12, &md5_length);
    198                        }
    199                        if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) {
    200                            sha1_digest =
    201                                ATOB_AsciiToData(buf + 13, &sha1_length);
    202                        }
    203                        if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) {
    204                            sha1_digest =
    205                                ATOB_AsciiToData(buf + 12, &sha1_length);
    206                        }
    207                    }
    208 
    209                    globaldig = jar->globalmeta;
    210 
    211                    if (globaldig && md5_digest && verbosity >= 0) {
    212                        PR_fprintf(outputFD,
    213                                   "  md5 digest on global metainfo: %s\n",
    214                                   PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
    215                                       ? "no match"
    216                                       : "match");
    217                    }
    218 
    219                    if (globaldig && sha1_digest && verbosity >= 0) {
    220                        PR_fprintf(outputFD,
    221                                   "  sha digest on global metainfo: %s\n",
    222                                   PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
    223                                       ? "no match"
    224                                       : "match");
    225                    }
    226 
    227                    if (globaldig == NULL && verbosity >= 0) {
    228                        PR_fprintf(outputFD,
    229                                   "global metadigest is not available, strange.\n");
    230                    }
    231 
    232                    PORT_Free(md5_digest);
    233                    PORT_Free(sha1_digest);
    234                    fclose(fp);
    235                }
    236            }
    237        }
    238    }
    239 
    240    JAR_find_end(ctx);
    241 
    242    return retval;
    243 }
    244 
    245 /************************************************************************
    246 *
    247 * J a r W h o
    248 */
    249 int
    250 JarWho(char *filename)
    251 {
    252    FILE *fp;
    253 
    254    JAR *jar;
    255    JAR_Context *ctx;
    256 
    257    int status;
    258    int retval = 0;
    259 
    260    JAR_Item *it;
    261    JAR_Cert *fing;
    262 
    263    CERTCertificate *cert, *prev = NULL;
    264 
    265    jar = JAR_new();
    266 
    267    if ((fp = fopen(filename, "r")) == NULL) {
    268        perror(filename);
    269        exit(ERRX);
    270    }
    271    fclose(fp);
    272 
    273    status = JAR_pass_archive(jar, jarArchGuess, filename, "some-url");
    274 
    275    if (status < 0 || jar->valid < 0) {
    276        PR_fprintf(outputFD,
    277                   "NOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
    278                   filename);
    279        retval = -1;
    280        if (jar->valid < 0 || status != -1) {
    281            const char *errtext;
    282 
    283            if (status >= JAR_BASE && status <= JAR_BASE_END) {
    284                errtext = JAR_get_error(status);
    285            } else {
    286                errtext = SECU_Strerror(PORT_GetError());
    287            }
    288 
    289            PR_fprintf(outputFD, "  (reported reason: %s)\n\n", errtext);
    290        }
    291    }
    292 
    293    PR_fprintf(outputFD, "\nSigner information:\n\n");
    294 
    295    ctx = JAR_find(jar, NULL, jarTypeSign);
    296 
    297    while (JAR_find_next(ctx, &it) >= 0) {
    298        fing = (JAR_Cert *)it->data;
    299        cert = fing->cert;
    300 
    301        if (cert) {
    302            if (prev == cert)
    303                break;
    304 
    305            if (cert->nickname)
    306                PR_fprintf(outputFD, "nickname: %s\n", cert->nickname);
    307            if (cert->subjectName)
    308                PR_fprintf(outputFD, "subject name: %s\n",
    309                           cert->subjectName);
    310            if (cert->issuerName)
    311                PR_fprintf(outputFD, "issuer name: %s\n", cert->issuerName);
    312        } else {
    313            PR_fprintf(outputFD, "no certificate could be found\n");
    314            retval = -1;
    315        }
    316 
    317        prev = cert;
    318    }
    319 
    320    JAR_find_end(ctx);
    321 
    322    JAR_destroy(jar);
    323    return retval;
    324 }
    325 
    326 /************************************************************************
    327 * j a r _ c b
    328 */
    329 static int
    330 jar_cb(int status, JAR *jar, const char *metafile,
    331       char *pathname, char *errortext)
    332 {
    333    PR_fprintf(errorFD, "error %d: %s IN FILE %s\n", status, errortext,
    334               pathname);
    335    errorCount++;
    336    return 0;
    337 }