/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"signtool.h" #include"zip.h" #include"prmem.h" #include"blapi.h" #include"sechash.h"/* for HASH_GetHashObject() */
/* * S i g n A r c h i v e * * Sign an individual archive tree. A directory * called META-INF is created underneath this. *
*/ int
SignArchive(char *tree, char *keyName, char *zip_file, int javascript, char *meta_file, char *install_script, int _optimize, PRBool recurse)
{ int status; char tempfn[FNSIZE], fullfn[FNSIZE]; int keyType = rsaKey; int count;
metafile = meta_file;
optimize = _optimize;
/* To create XPI compatible Archive manifesto() must be run before * the zipfile is opened. This is so the signed files are not added
* the archive before the crucial rsa/dsa file*/ if (xpi_arc) {
manifesto(tree, install_script, recurse);
}
if (zip_file) {
zipfile = JzipOpen(zip_file, NULL /*no comment*/);
}
/*Sign and add files to the archive normally with manifesto()*/ if (!xpi_arc) {
manifesto(tree, install_script, recurse);
}
if (keyName) {
status = create_pk7(tree, keyName, &keyType); if (status < 0) {
PR_fprintf(errorFD, "the tree \"%s\" was NOT SUCCESSFULLY SIGNED\n",
tree);
errorCount++; exit(ERRX);
}
}
/* Add the rsa/dsa file as the first file in the archive. This is crucial
* for a XPInstall compatible archive */ if (xpi_arc) { if (verbosity >= 0) {
PR_fprintf(outputFD, "%s \n", XPI_TEXT);
}
/* rsa/dsa to zip */
count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa")); if (count >= sizeof(tempfn)) {
PR_fprintf(errorFD, "unable to write key metadata\n");
errorCount++; exit(ERRX);
}
count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); if (count >= sizeof(fullfn)) {
PR_fprintf(errorFD, "unable to write key metadata\n");
errorCount++; exit(ERRX);
}
JzipAdd(fullfn, tempfn, zipfile, compression_level);
/* Loop through all files & subdirectories, add to archive */
foreach (tree, "", manifesto_xpi_fn, recurse, PR_FALSE /*include dirs */,
(void *)NULL)
;
} /* mf to zip */
strcpy(tempfn, "META-INF/manifest.mf");
count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); if (count >= sizeof(fullfn)) {
PR_fprintf(errorFD, "unable to write manifest\n");
errorCount++; exit(ERRX);
}
JzipAdd(fullfn, tempfn, zipfile, compression_level);
/* sf to zip */
count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.sf", base); if (count >= sizeof(tempfn)) {
PR_fprintf(errorFD, "unable to write sf metadata\n");
errorCount++; exit(ERRX);
}
count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); if (count >= sizeof(fullfn)) {
PR_fprintf(errorFD, "unable to write sf metadata\n");
errorCount++; exit(ERRX);
}
JzipAdd(fullfn, tempfn, zipfile, compression_level);
/* Add the rsa/dsa file to the zip archive normally */ if (!xpi_arc) { /* rsa/dsa to zip */
count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa")); if (count >= sizeof(tempfn)) {
PR_fprintf(errorFD, "unable to write key metadata\n");
errorCount++; exit(ERRX);
}
count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); if (count >= sizeof(fullfn)) {
PR_fprintf(errorFD, "unable to write key metadata\n");
errorCount++; exit(ERRX);
}
JzipAdd(fullfn, tempfn, zipfile, compression_level);
}
JzipClose(zipfile);
if (verbosity >= 0) { if (javascript) {
PR_fprintf(outputFD, "jarfile \"%s\" signed successfully\n",
zip_file);
} else {
PR_fprintf(outputFD, "tree \"%s\" signed successfully\n",
tree);
}
}
return 0;
}
typedefstruct { char *keyName; int javascript; char *metafile; char *install_script; int optimize;
} SignArcInfo;
/* * S i g n A l l A r c * * Javascript may generate multiple .arc directories, one * for each jar archive needed. Sign them all. *
*/ int
SignAllArc(char *jartree, char *keyName, int javascript, char *metafilename, char *install_script, int optimize_level, PRBool recurse)
{
SignArcInfo info;
/* Make sure there is one and only one ".arc" in the relative path,
* and that it is at the end of the path (don't sign .arcs within .arcs) */ if ((PL_strcaserstr(relpath, ".arc") == relpath + strlen(relpath) - 4) &&
(PL_strcasestr(relpath, ".arc") == relpath + strlen(relpath) - 4)) {
/********************************************************************* * * c r e a t e _ p k 7
*/ staticint
create_pk7(char *dir, char *keyName, int *keyType)
{ int status = 0; char *file_ext;
CERTCertificate *cert;
CERTCertDBHandle *db;
FILE *in, *out;
char sf_file[FNSIZE]; char pk7_file[FNSIZE];
/* open cert database */
db = CERT_GetDefaultCertDB();
if (status) {
PR_fprintf(errorFD, "%s: PROBLEM signing data (%s)\n",
PROGRAM_NAME, SECU_Strerror(PORT_GetError()));
errorCount++; return -1;
}
return 0;
}
/* * j a r _ f i n d _ k e y _ t y p e * * Determine the key type for a given cert, which * should be rsaKey or dsaKey. Any error return 0. *
*/ staticint
jar_find_key_type(CERTCertificate *cert)
{
SECKEYPrivateKey *privk = NULL;
KeyType keyType;
/* determine its type */
privk = PK11_FindKeyByAnyCert(cert, &pwdata); if (privk == NULL) {
PR_fprintf(errorFD, "warning - can't find private key for this cert\n");
warningCount++; return 0;
}
/* * m a n i f e s t o * * Run once for every subdirectory in which a * manifest is to be created -- usually exactly once. *
*/ staticint
manifesto(char *dirname, char *install_script, PRBool recurse)
{ char metadir[FNSIZE], sfname[FNSIZE];
/* Create the META-INF directory to hold signing info */
if (PR_Access(dirname, PR_ACCESS_READ_OK)) {
PR_fprintf(errorFD, "%s: unable to read your directory: %s\n",
PROGRAM_NAME, dirname);
errorCount++;
perror(dirname); exit(ERRX);
}
if (PR_Access(dirname, PR_ACCESS_WRITE_OK)) {
PR_fprintf(errorFD, "%s: unable to write to your directory: %s\n",
PROGRAM_NAME, dirname);
errorCount++;
perror(dirname); exit(ERRX);
}
if ((mf = fopen(metadir, "wb")) == NULL) {
perror(MANIFEST);
PR_fprintf(errorFD, "%s: Probably, the directory you are trying to" " sign has\n",
PROGRAM_NAME);
PR_fprintf(errorFD, "%s: permissions problems or may not exist.\n",
PROGRAM_NAME);
errorCount++; exit(ERRX);
}
if (scriptdir) {
fprintf(mf, "Comments: --\n");
fprintf(mf, "Comments: --\n");
fprintf(mf, "Comments: -- This archive signs Javascripts which may not necessarily\n");
fprintf(mf, "Comments: -- be included in the physical jar file.\n");
fprintf(mf, "Comments: --\n");
fprintf(mf, "Comments: --\n");
}
if (install_script)
fprintf(mf, "Install-Script: %s\n", install_script);
if (metafile)
add_meta(mf, "+");
/* Loop through all files & subdirectories */
foreach (dirname, "", manifesto_fn, recurse, PR_FALSE /*include dirs */,
(void *)NULL)
;
/* * m a n i f e s t o _ x p i _ f n * * Called by pointer from SignArchive(), once for * each file within the directory. This function * is only used for adding to XPI compatible archive *
*/ staticint
manifesto_xpi_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
{ char fullname[FNSIZE]; int count;
if (verbosity >= 0) {
PR_fprintf(outputFD, "--> %s\n", relpath);
}
/* * m a n i f e s t o _ f n * * Called by pointer from manifesto(), once for * each file within the directory. *
*/ staticint
manifesto_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
{ int use_js; char *md5, *sha1;
JAR_Digest dig; char fullname[FNSIZE];
if (verbosity >= 0) {
PR_fprintf(outputFD, "--> %s\n", relpath);
}
/* extension matching */ if (extensionsGiven) { char *ext = PL_strrchr(relpath, '.'); if (!ext) return 0; if (!PL_HashTableLookup(extensions, ext)) return 0;
}
if (!use_js) {
JzipAdd(fullname, relpath, zipfile, compression_level);
}
return 0;
}
/* * a d d _ m e t a * * Parse the metainfo file, and add any details * necessary to the manifest file. In most cases you * should be using the -i option (ie, for SmartUpdate). *
*/ staticint
add_meta(FILE *fp, char *name)
{
FILE *met; char buf[BUFSIZ];
int place; char *pattern, *meta;
int num = 0;
if ((met = fopen(metafile, "r")) != NULL) { while (fgets(buf, BUFSIZ, met)) { char *s;
for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
;
*s = 0;
if (*buf == 0) continue;
pattern = buf;
/* skip to whitespace */ for (s = buf; *s && *s != ' ' && *s != '\t'; s++)
;
/********************************************************************** * * S i g n F i l e
*/ staticint
SignFile(FILE *outFile, FILE *inFile, CERTCertificate *cert)
{ int nb; char ibuf[4096], digestdata[32]; const SECHashObject *hashObj; void *hashcx; unsignedint len;
/* * g e n e r a t e _ S F _ f i l e * * From the supplied manifest file, calculates * digests on the various sections, creating a .SF * file in the process. *
*/ staticint
generate_SF_file(char *manifile, char *who)
{
FILE *sfFile;
FILE *mfFile; long r1, r2, r3; char whofile[FNSIZE]; char *buf, *name = NULL; char *md5, *sha1;
JAR_Digest dig; int line = 0;
/* restore normalcy after changing offset position */
fseek(mfFile, r3, SEEK_SET);
}
PORT_Free(buf);
PORT_Free(name);
fclose(sfFile);
fclose(mfFile);
return 0;
}
/* * c a l c u l a t e _ M D 5 _ r a n g e * * Calculate the MD5 digest on a range of bytes in * the specified fopen'd file. Returns base64. *
*/ staticint
calculate_MD5_range(FILE *fp, long r1, long r2, JAR_Digest *dig)
{ int num; int range; unsignedchar *buf;
SECStatus rv;
range = r2 - r1;
/* position to the beginning of range */
fseek(fp, r1, SEEK_SET);
buf = (unsignedchar *)PORT_ZAlloc(range); if (buf == NULL)
out_of_memory();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.