security/nss/cmd/signtool/verify.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/signtool/verify.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,339 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "signtool.h"
     1.9 +
    1.10 +
    1.11 +static int	jar_cb(int status, JAR *jar, const char *metafile, 
    1.12 +char *pathname, char *errortext);
    1.13 +static int	verify_global (JAR *jar);
    1.14 +
    1.15 +/*************************************************************************
    1.16 + *
    1.17 + * V e r i f y J a r
    1.18 + */
    1.19 +int
    1.20 +VerifyJar(char *filename)
    1.21 +{
    1.22 +    FILE * fp;
    1.23 +
    1.24 +    int	ret;
    1.25 +    int	status;
    1.26 +    int	failed = 0;
    1.27 +    char	*err;
    1.28 +
    1.29 +    JAR * jar;
    1.30 +    JAR_Context * ctx;
    1.31 +
    1.32 +    JAR_Item * it;
    1.33 +
    1.34 +    jar = JAR_new();
    1.35 +
    1.36 +    if ((fp = fopen (filename, "r")) == NULL) {
    1.37 +	perror (filename);
    1.38 +	exit (ERRX);
    1.39 +    } else
    1.40 +	fclose (fp);
    1.41 +
    1.42 +    JAR_set_callback (JAR_CB_SIGNAL, jar, jar_cb);
    1.43 +
    1.44 +
    1.45 +    status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
    1.46 +
    1.47 +    if (status < 0 || jar->valid < 0) {
    1.48 +	failed = 1;
    1.49 +	PR_fprintf(outputFD, 
    1.50 +	    "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
    1.51 +	     filename);
    1.52 +	if (status < 0) {
    1.53 +	    const char	*errtext;
    1.54 +
    1.55 +	    if (status >= JAR_BASE && status <= JAR_BASE_END) {
    1.56 +		errtext = JAR_get_error (status);
    1.57 +	    } else {
    1.58 +		errtext = SECU_Strerror(PORT_GetError());
    1.59 +	    }
    1.60 +
    1.61 +	    PR_fprintf(outputFD, "  (reported reason: %s)\n\n",
    1.62 +	         errtext);
    1.63 +
    1.64 +	    /* corrupt files should not have their contents listed */
    1.65 +
    1.66 +	    if (status == JAR_ERR_CORRUPT)
    1.67 +		return - 1;
    1.68 +	}
    1.69 +	PR_fprintf(outputFD,
    1.70 +	    "entries shown below will have their digests checked only.\n");
    1.71 +	jar->valid = 0;
    1.72 +    } else
    1.73 +	PR_fprintf(outputFD,
    1.74 +	    "archive \"%s\" has passed crypto verification.\n", filename);
    1.75 +
    1.76 +    if (verify_global (jar))
    1.77 +	failed = 1;
    1.78 +
    1.79 +    PR_fprintf(outputFD, "\n");
    1.80 +    PR_fprintf(outputFD, "%16s   %s\n", "status", "path");
    1.81 +    PR_fprintf(outputFD, "%16s   %s\n", "------------", "-------------------");
    1.82 +
    1.83 +    ctx = JAR_find (jar, NULL, jarTypeMF);
    1.84 +
    1.85 +    while (JAR_find_next (ctx, &it) >= 0) {
    1.86 +	if (it && it->pathname) {
    1.87 +	    rm_dash_r(TMP_OUTPUT);
    1.88 +	    ret = JAR_verified_extract (jar, it->pathname, TMP_OUTPUT);
    1.89 +	    /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
    1.90 +	    if (ret < 0) 
    1.91 +		failed = 1;
    1.92 +
    1.93 +	    if (ret == JAR_ERR_PNF)
    1.94 +		err = "NOT PRESENT";
    1.95 +	    else if (ret == JAR_ERR_HASH)
    1.96 +		err = "HASH FAILED";
    1.97 +	    else
    1.98 +		err = "NOT VERIFIED";
    1.99 +
   1.100 +	    PR_fprintf(outputFD, "%16s   %s\n", 
   1.101 +	        ret >= 0 ? "verified" : err, it->pathname);
   1.102 +
   1.103 +	    if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
   1.104 +		PR_fprintf(outputFD, "      (reason: %s)\n",
   1.105 +		     JAR_get_error (ret));
   1.106 +	}
   1.107 +    }
   1.108 +
   1.109 +    JAR_find_end (ctx);
   1.110 +
   1.111 +    if (status < 0 || jar->valid < 0) {
   1.112 +	failed = 1;
   1.113 +	PR_fprintf(outputFD,
   1.114 +	    "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
   1.115 +	     filename);
   1.116 +	give_help (status);
   1.117 +    }
   1.118 +
   1.119 +    JAR_destroy (jar);
   1.120 +
   1.121 +    if (failed)
   1.122 +	return - 1;
   1.123 +    return 0;
   1.124 +}
   1.125 +
   1.126 +
   1.127 +/***************************************************************************
   1.128 + *
   1.129 + * v e r i f y _ g l o b a l
   1.130 + */
   1.131 +static int	
   1.132 +verify_global (JAR *jar)
   1.133 +{
   1.134 +    FILE        * fp;
   1.135 +    JAR_Context * ctx;
   1.136 +    JAR_Item    * it;
   1.137 +    JAR_Digest  * globaldig;
   1.138 +    char	* ext;
   1.139 +    unsigned char *md5_digest, *sha1_digest;
   1.140 +    unsigned int  sha1_length, md5_length;
   1.141 +    int	          retval = 0;
   1.142 +    char	  buf [BUFSIZ];
   1.143 +
   1.144 +    ctx = JAR_find (jar, "*", jarTypePhy);
   1.145 +
   1.146 +    while (JAR_find_next (ctx, &it) >= 0) {
   1.147 +	if (!PORT_Strncmp (it->pathname, "META-INF", 8)) {
   1.148 +	    for (ext = it->pathname; *ext; ext++)
   1.149 +		;
   1.150 +	    while (ext > it->pathname && *ext != '.') 
   1.151 +		ext--;
   1.152 +
   1.153 +	    if (verbosity >= 0) {
   1.154 +		if (!PORT_Strcasecmp (ext, ".rsa")) {
   1.155 +		    PR_fprintf(outputFD, "found a RSA signature file: %s\n",
   1.156 +		         				  it->pathname);
   1.157 +		}
   1.158 +
   1.159 +		if (!PORT_Strcasecmp (ext, ".dsa")) {
   1.160 +		    PR_fprintf(outputFD, "found a DSA signature file: %s\n",
   1.161 +		         				  it->pathname);
   1.162 +		}
   1.163 +
   1.164 +		if (!PORT_Strcasecmp (ext, ".mf")) {
   1.165 +		    PR_fprintf(outputFD,
   1.166 +		        "found a MF master manifest file: %s\n",
   1.167 +		         it->pathname);
   1.168 +		}
   1.169 +	    }
   1.170 +
   1.171 +	    if (!PORT_Strcasecmp (ext, ".sf")) {
   1.172 +		if (verbosity >= 0) {
   1.173 +		    PR_fprintf(outputFD,
   1.174 +		        "found a SF signature manifest file: %s\n",
   1.175 +		         it->pathname);
   1.176 +		}
   1.177 +
   1.178 +		rm_dash_r(TMP_OUTPUT);
   1.179 +		if (JAR_extract (jar, it->pathname, TMP_OUTPUT) < 0) {
   1.180 +		    PR_fprintf(errorFD, "%s: error extracting %s\n",
   1.181 +		         PROGRAM_NAME, it->pathname);
   1.182 +		    errorCount++;
   1.183 +		    retval = -1;
   1.184 +		    continue;
   1.185 +		}
   1.186 +
   1.187 +		md5_digest = NULL;
   1.188 +		sha1_digest = NULL;
   1.189 +
   1.190 +		if ((fp = fopen (TMP_OUTPUT, "rb")) != NULL) {
   1.191 +		    while (fgets (buf, BUFSIZ, fp)) {
   1.192 +			char	*s;
   1.193 +
   1.194 +			if (*buf == 0 || *buf == '\n' || *buf == '\r') 
   1.195 +			    break;
   1.196 +
   1.197 +			for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
   1.198 +			    ;
   1.199 +			*s = 0;
   1.200 +
   1.201 +			if (!PORT_Strncmp (buf, "MD5-Digest: ", 12)) {
   1.202 +			    md5_digest = 
   1.203 +				ATOB_AsciiToData (buf + 12, &md5_length);
   1.204 +			}
   1.205 +			if (!PORT_Strncmp (buf, "SHA1-Digest: ", 13)) {
   1.206 +			    sha1_digest = 
   1.207 +				ATOB_AsciiToData (buf + 13, &sha1_length);
   1.208 +			}
   1.209 +			if (!PORT_Strncmp (buf, "SHA-Digest: ", 12)) {
   1.210 +			    sha1_digest = 
   1.211 +				ATOB_AsciiToData (buf + 12, &sha1_length);
   1.212 +			}
   1.213 +		    }
   1.214 +
   1.215 +		    globaldig = jar->globalmeta;
   1.216 +
   1.217 +		    if (globaldig && md5_digest && verbosity >= 0) {
   1.218 +			PR_fprintf(outputFD,
   1.219 +			   "  md5 digest on global metainfo: %s\n",
   1.220 +			    PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
   1.221 +			    ? "no match" : "match");
   1.222 +		    }
   1.223 +
   1.224 +		    if (globaldig && sha1_digest && verbosity >= 0) {
   1.225 +			PR_fprintf(outputFD,
   1.226 +			    "  sha digest on global metainfo: %s\n",
   1.227 +			    PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH) 
   1.228 +			    ? "no match" : "match");
   1.229 +		    }
   1.230 +
   1.231 +		    if (globaldig == NULL && verbosity >= 0) {
   1.232 +			PR_fprintf(outputFD,
   1.233 +			     "global metadigest is not available, strange.\n");
   1.234 +		    }
   1.235 +
   1.236 +		    fclose (fp);
   1.237 +		}
   1.238 +	    }
   1.239 +	}
   1.240 +    }
   1.241 +
   1.242 +    JAR_find_end (ctx);
   1.243 +
   1.244 +    return retval;
   1.245 +}
   1.246 +
   1.247 +
   1.248 +/************************************************************************
   1.249 + *
   1.250 + * J a r W h o
   1.251 + */
   1.252 +int
   1.253 +JarWho(char *filename)
   1.254 +{
   1.255 +    FILE * fp;
   1.256 +
   1.257 +    JAR * jar;
   1.258 +    JAR_Context * ctx;
   1.259 +
   1.260 +    int	status;
   1.261 +    int	retval = 0;
   1.262 +
   1.263 +    JAR_Item * it;
   1.264 +    JAR_Cert * fing;
   1.265 +
   1.266 +    CERTCertificate * cert, *prev = NULL;
   1.267 +
   1.268 +    jar = JAR_new();
   1.269 +
   1.270 +    if ((fp = fopen (filename, "r")) == NULL) {
   1.271 +	perror (filename);
   1.272 +	exit (ERRX);
   1.273 +    } 
   1.274 +    fclose (fp);
   1.275 +
   1.276 +    status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
   1.277 +
   1.278 +    if (status < 0 || jar->valid < 0) {
   1.279 +	PR_fprintf(outputFD,
   1.280 +	    "NOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
   1.281 +	     filename);
   1.282 +	retval = -1;
   1.283 +	if (jar->valid < 0 || status != -1) {
   1.284 +	    const char	*errtext;
   1.285 +
   1.286 +	    if (status >= JAR_BASE && status <= JAR_BASE_END) {
   1.287 +		errtext = JAR_get_error (status);
   1.288 +	    } else {
   1.289 +		errtext = SECU_Strerror(PORT_GetError());
   1.290 +	    }
   1.291 +
   1.292 +	    PR_fprintf(outputFD, "  (reported reason: %s)\n\n", errtext);
   1.293 +	}
   1.294 +    }
   1.295 +
   1.296 +    PR_fprintf(outputFD, "\nSigner information:\n\n");
   1.297 +
   1.298 +    ctx = JAR_find (jar, NULL, jarTypeSign);
   1.299 +
   1.300 +    while (JAR_find_next (ctx, &it) >= 0) {
   1.301 +	fing = (JAR_Cert * ) it->data;
   1.302 +	cert = fing->cert;
   1.303 +
   1.304 +	if (cert) {
   1.305 +	    if (prev == cert)
   1.306 +		break;
   1.307 +
   1.308 +	    if (cert->nickname)
   1.309 +		PR_fprintf(outputFD, "nickname: %s\n", cert->nickname);
   1.310 +	    if (cert->subjectName)
   1.311 +		PR_fprintf(outputFD, "subject name: %s\n",
   1.312 +		     cert->subjectName);
   1.313 +	    if (cert->issuerName)
   1.314 +		PR_fprintf(outputFD, "issuer name: %s\n", cert->issuerName);
   1.315 +	} else {
   1.316 +	    PR_fprintf(outputFD, "no certificate could be found\n");
   1.317 +	    retval = -1;
   1.318 +	}
   1.319 +
   1.320 +	prev = cert;
   1.321 +    }
   1.322 +
   1.323 +    JAR_find_end (ctx);
   1.324 +
   1.325 +    JAR_destroy (jar);
   1.326 +    return retval;
   1.327 +}
   1.328 +
   1.329 +
   1.330 +/************************************************************************
   1.331 + * j a r _ c b
   1.332 + */
   1.333 +static int	jar_cb(int status, JAR *jar, const char *metafile,
   1.334 +char *pathname, char *errortext)
   1.335 +{
   1.336 +    PR_fprintf(errorFD, "error %d: %s IN FILE %s\n", status, errortext,
   1.337 +         pathname);
   1.338 +    errorCount++;
   1.339 +    return 0;
   1.340 +}
   1.341 +
   1.342 +

mercurial