diff options
Diffstat (limited to 'security/nss/cmd/signtool/sign.c')
-rw-r--r-- | security/nss/cmd/signtool/sign.c | 861 |
1 files changed, 0 insertions, 861 deletions
diff --git a/security/nss/cmd/signtool/sign.c b/security/nss/cmd/signtool/sign.c deleted file mode 100644 index 58a72ebef..000000000 --- a/security/nss/cmd/signtool/sign.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include "signtool.h" -#include "zip.h" -#include "prmem.h" -#include "blapi.h" - -static int create_pk7 (char *dir, char *keyName, int *keyType); -static int jar_find_key_type (CERTCertificate *cert); -static int manifesto (char *dirname, char *install_script, PRBool recurse); -static int manifesto_fn(char *relpath, char *basedir, char *reldir, - char *filename, void *arg); -static int sign_all_arc_fn(char *relpath, char *basedir, char *reldir, - char *filename, void *arg); -static int add_meta (FILE *fp, char *name); -static int SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert); -static int generate_SF_file (char *manifile, char *who); -static int calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig); -static void SignOut (void *arg, const char *buf, unsigned long len); - -static char *metafile = NULL; -static int optimize = 0; -static FILE *mf; -static ZIPfile *zipfile=NULL; - -/* - * 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; - - metafile = meta_file; - optimize = _optimize; - - if(zip_file) { - zipfile = JzipOpen(zip_file, NULL /*no comment*/); - } - - 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); - } - } - - /* mf to zip */ - - strcpy (tempfn, "META-INF/manifest.mf"); - sprintf (fullfn, "%s/%s", tree, tempfn); - JzipAdd(fullfn, tempfn, zipfile, compression_level); - - /* sf to zip */ - - sprintf (tempfn, "META-INF/%s.sf", base); - sprintf (fullfn, "%s/%s", tree, tempfn); - JzipAdd(fullfn, tempfn, zipfile, compression_level); - - /* rsa/dsa to zip */ - - sprintf (tempfn, "META-INF/%s.%s", base, (keyType==dsaKey ? "dsa" : "rsa")); - sprintf (fullfn, "%s/%s", tree, tempfn); - 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; -} - -typedef struct { - 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 *metafile, - char *install_script, int optimize, PRBool recurse) -{ - SignArcInfo info; - - info.keyName = keyName; - info.javascript = javascript; - info.metafile = metafile; - info.install_script = install_script; - info.optimize = optimize; - - return foreach(jartree, "", sign_all_arc_fn, recurse, - PR_TRUE /*include dirs*/, (void*)&info); -} - -static int -sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename, - void *arg) -{ - char *zipfile=NULL; - char *arc=NULL, *archive=NULL; - int retval=0; - SignArcInfo *infop = (SignArcInfo*)arg; - - /* 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) ) { - - if(!infop) { - retval = -1; - goto finish; - } - archive = PR_smprintf("%s/%s", basedir, relpath); - - zipfile = PL_strdup(archive); - arc = PORT_Strrchr (zipfile, '.'); - - if (arc == NULL) { - PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME); - errorCount++; - retval = -1; - goto finish; - } - - PL_strcpy (arc, ".jar"); - - if(verbosity >= 0) { - PR_fprintf(outputFD, "\nsigning: %s\n", zipfile); - } - retval = SignArchive(archive, infop->keyName, zipfile, - infop->javascript, infop->metafile, infop->install_script, - infop->optimize, PR_TRUE /* recurse */); - } -finish: - if(archive) PR_Free(archive); - if(zipfile) PR_Free(zipfile); - - return retval; -} - -/********************************************************************* - * - * c r e a t e _ p k 7 - */ -static int -create_pk7 (char *dir, char *keyName, int *keyType) -{ - int status = 0; - char *file_ext; - - CERTCertificate *cert; - CERTCertDBHandle *db; - - SECKEYKeyDBHandle *keyHandle; - - FILE *in, *out; - - char sf_file [FNSIZE]; - char pk7_file [FNSIZE]; - - /* open key database */ - keyHandle = SECU_OpenKeyDB(PR_TRUE /*readOnly*/); - - if (keyHandle == NULL) - return -1; - - SECKEY_SetDefaultKeyDB (keyHandle); - - /* open cert database */ - db = OpenCertDB(PR_TRUE /*readOnly*/); - - if (db == NULL) - return -1; - - - /* find cert */ - /*cert = CERT_FindCertByNicknameOrEmailAddr(db, keyName);*/ - cert = PK11_FindCertFromNickname(keyName, NULL /*wincx*/); - - if (cert == NULL) - { - SECU_PrintError - ( - PROGRAM_NAME, - "the cert \"%s\" does not exist in the database", - keyName - ); - return -1; - } - - - /* determine the key type, which sets the extension for pkcs7 object */ - - *keyType = jar_find_key_type (cert); - file_ext = (*keyType == dsaKey) ? "dsa" : "rsa"; - - sprintf (sf_file, "%s/META-INF/%s.sf", dir, base); - sprintf (pk7_file, "%s/META-INF/%s.%s", dir, base, file_ext); - - if ((in = fopen (sf_file, "rb")) == NULL) - { - PR_fprintf(errorFD, "%s: Can't open %s for reading\n", PROGRAM_NAME, sf_file); - errorCount++; - exit (ERRX); - } - - if ((out = fopen (pk7_file, "wb")) == NULL) - { - PR_fprintf(errorFD, "%s: Can't open %s for writing\n", PROGRAM_NAME, sf_file); - errorCount++; - exit (ERRX); - } - - status = SignFile (out, in, cert); - - fclose (in); - fclose (out); - - if (status) - { - PR_fprintf(errorFD, "%s: PROBLEM signing data (%s)\n", - PROGRAM_NAME, SECU_ErrorString ((int16) 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. - * - */ -static int -jar_find_key_type (CERTCertificate *cert) -{ - PK11SlotInfo *slot = NULL; - SECKEYPrivateKey *privk = NULL; - - /* determine its type */ - PK11_FindObjectForCert (cert, /*wincx*/ NULL, &slot); - - if (slot == NULL) - { - PR_fprintf(errorFD, "warning - can't find slot for this cert\n"); - warningCount++; - return 0; - } - - privk = PK11_FindPrivateKeyFromCert (slot, cert, /*wincx*/ NULL); - - if (privk == NULL) - { - PR_fprintf(errorFD, "warning - can't find private key for this cert\n"); - warningCount++; - return 0; - } - - return privk->keyType; - } - - -/* - * 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. - * - */ -static int -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); - } - - sprintf (metadir, "%s/META-INF", dirname); - - strcpy (sfname, metadir); - - PR_MkDir (metadir, 0777); - - strcat (metadir, "/"); - strcat (metadir, MANIFEST); - - 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(verbosity >= 0) { - PR_fprintf(outputFD, "Generating %s file..\n", metadir); - } - - fprintf(mf, "Manifest-Version: 1.0\n"); - fprintf (mf, "Created-By: %s\n", CREATOR); - fprintf (mf, "Comments: %s\n", BREAKAGE); - - 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); - - fclose (mf); - - strcat (sfname, "/"); - strcat (sfname, base); - strcat (sfname, ".sf"); - - if(verbosity >= 0) { - PR_fprintf(outputFD, "Generating %s.sf file..\n", base); - } - generate_SF_file (metadir, sfname); - - return 0; -} - -/* - * m a n i f e s t o _ f n - * - * Called by pointer from manifesto(), once for - * each file within the directory. - * - */ -static int manifesto_fn - (char *relpath, char *basedir, char *reldir, char *filename, void *arg) -{ - int use_js; - - JAR_Digest dig; - char fullname [FNSIZE]; - - if(verbosity >= 0) { - PR_fprintf(outputFD, "--> %s\n", relpath); - } - - /* extension matching */ - if(extensionsGiven) { - char *ext; - - ext = PL_strrchr(relpath, '.'); - if(!ext) { - return 0; - } else { - if(!PL_HashTableLookup(extensions, ext)) { - return 0; - } - } - } - - sprintf (fullname, "%s/%s", basedir, relpath); - - fprintf (mf, "\n"); - - use_js = 0; - - if (scriptdir && !PORT_Strcmp (scriptdir, reldir)) - use_js++; - - /* sign non-.js files inside .arc directories - using the javascript magic */ - - if ( (PL_strcaserstr(filename, ".js") != filename + strlen(filename) - 3) - && (PL_strcaserstr(reldir, ".arc") == reldir + strlen(filename)-4)) - use_js++; - - if (use_js) - { - fprintf (mf, "Name: %s\n", filename); - fprintf (mf, "Magic: javascript\n"); - - if (optimize == 0) - fprintf (mf, "javascript.id: %s\n", filename); - - if (metafile) - add_meta (mf, filename); - } - else - { - fprintf (mf, "Name: %s\n", relpath); - if (metafile) - add_meta (mf, relpath); - } - - JAR_digest_file (fullname, &dig); - - - if (optimize == 0) - { - fprintf (mf, "Digest-Algorithms: MD5 SHA1\n"); - fprintf (mf, "MD5-Digest: %s\n", BTOA_DataToAscii (dig.md5, MD5_LENGTH)); - } - - fprintf (mf, "SHA1-Digest: %s\n", BTOA_DataToAscii (dig.sha1, SHA1_LENGTH)); - - 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). - * - */ -static int 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++); - - /* terminate pattern */ - if (*s == ' ' || *s == '\t') *s++ = 0; - - /* eat through whitespace */ - while (*s == ' ' || *s == '\t') s++; - - meta = s; - - /* this will eventually be regexp matching */ - - place = 0; - if (!PORT_Strcmp (pattern, name)) - place = 1; - - if (place) - { - num++; - if(verbosity >= 0) { - PR_fprintf(outputFD, "[%s] %s\n", name, meta); - } - fprintf (fp, "%s\n", meta); - } - } - fclose (met); - } - else - { - PR_fprintf(errorFD, "%s: can't open metafile: %s\n", PROGRAM_NAME, metafile); - errorCount++; - exit (ERRX); - } - - return num; -} - -/********************************************************************** - * - * S i g n F i l e - */ -static int -SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert) -{ - int nb; - char ibuf[4096], digestdata[32]; - SECHashObject *hashObj; - void *hashcx; - unsigned int len; - - SECItem digest; - SEC_PKCS7ContentInfo *cinfo; - SECStatus rv; - - if (outFile == NULL || inFile == NULL || cert == NULL) - return -1; - - /* XXX probably want to extend interface to allow other hash algorithms */ - hashObj = &SECHashObjects[HASH_AlgSHA1]; - - hashcx = (* hashObj->create)(); - if (hashcx == NULL) - return -1; - - (* hashObj->begin)(hashcx); - - for (;;) - { - if (feof(inFile)) break; - nb = fread(ibuf, 1, sizeof(ibuf), inFile); - if (nb == 0) - { - if (ferror(inFile)) - { - PORT_SetError(SEC_ERROR_IO); - (* hashObj->destroy)(hashcx, PR_TRUE); - return -1; - } - /* eof */ - break; - } - (* hashObj->update)(hashcx, (unsigned char *) ibuf, nb); - } - - (* hashObj->end)(hashcx, (unsigned char *) digestdata, &len, 32); - (* hashObj->destroy)(hashcx, PR_TRUE); - - digest.data = (unsigned char *) digestdata; - digest.len = len; - - cinfo = SEC_PKCS7CreateSignedData - (cert, certUsageObjectSigner, NULL, - SEC_OID_SHA1, &digest, NULL, NULL); - - if (cinfo == NULL) - return -1; - - rv = SEC_PKCS7IncludeCertChain (cinfo, NULL); - if (rv != SECSuccess) - { - SEC_PKCS7DestroyContentInfo (cinfo); - return -1; - } - - if (no_time == 0) - { - rv = SEC_PKCS7AddSigningTime (cinfo); - if (rv != SECSuccess) - { - /* don't check error */ - } - } - - if(password) { - rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, password_hardcode, - NULL); - } else { - rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, SECU_GetPassword, - NULL); - } - - - SEC_PKCS7DestroyContentInfo (cinfo); - - if (rv != SECSuccess) - return -1; - - return 0; -} - -/* - * 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. - * - */ -static int generate_SF_file (char *manifile, char *who) -{ - FILE *sf; - FILE *mf; - - long r1, r2, r3; - - char whofile [FNSIZE]; - char *buf, *name; - - JAR_Digest dig; - - int line = 0; - - strcpy (whofile, who); - - if ((mf = fopen (manifile, "rb")) == NULL) - { - perror (manifile); - exit (ERRX); - } - - if ((sf = fopen (whofile, "wb")) == NULL) - { - perror (who); - exit (ERRX); - } - - buf = (char *) PORT_ZAlloc (BUFSIZ); - - if (buf) - name = (char *) PORT_ZAlloc (BUFSIZ); - - if (buf == NULL || name == NULL) - out_of_memory(); - - fprintf (sf, "Signature-Version: 1.0\n"); - fprintf (sf, "Created-By: %s\n", CREATOR); - fprintf (sf, "Comments: %s\n", BREAKAGE); - - if (fgets (buf, BUFSIZ, mf) == NULL) - { - PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME); - errorCount++; - exit (ERRX); - } - - if (strncmp (buf, "Manifest-Version:", 17)) - { - PR_fprintf(errorFD, "%s: not a manifest file!\n", PROGRAM_NAME); - errorCount++; - exit (ERRX); - } - - fseek (mf, 0L, SEEK_SET); - - /* Process blocks of headers, and calculate their hashen */ - - while (1) - { - /* Beginning range */ - r1 = ftell (mf); - - if (fgets (name, BUFSIZ, mf) == NULL) - break; - - line++; - - if (r1 != 0 && strncmp (name, "Name:", 5)) - { - PR_fprintf(errorFD, "warning: unexpected input in manifest file \"%s\" at line %d:\n", manifile, line); - PR_fprintf(errorFD, "%s\n", name); - warningCount++; - } - - while (fgets (buf, BUFSIZ, mf)) - { - if (*buf == 0 || *buf == '\n' || *buf == '\r') - break; - - line++; - - /* Ending range for hashing */ - r2 = ftell (mf); - } - - r3 = ftell (mf); - - if (r1) - { - fprintf (sf, "\n"); - fprintf (sf, "%s", name); - } - - calculate_MD5_range (mf, r1, r2, &dig); - - if (optimize == 0) - { - fprintf (sf, "Digest-Algorithms: MD5 SHA1\n"); - fprintf (sf, "MD5-Digest: %s\n", - BTOA_DataToAscii (dig.md5, MD5_LENGTH)); - } - - fprintf (sf, "SHA1-Digest: %s\n", - BTOA_DataToAscii (dig.sha1, SHA1_LENGTH)); - - /* restore normalcy after changing offset position */ - fseek (mf, r3, SEEK_SET); - } - - PORT_Free (buf); - PORT_Free (name); - - fclose (sf); - fclose (mf); - - 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. - * - */ -static int -calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig) -{ - int num; - int range; - unsigned char *buf; - - MD5Context *md5 = 0; - SHA1Context *sha1 = 0; - - unsigned int sha1_length, md5_length; - - range = r2 - r1; - - /* position to the beginning of range */ - fseek (fp, r1, SEEK_SET); - - buf = (unsigned char *) PORT_ZAlloc (range); - if (buf == NULL) - out_of_memory(); - - if ((num = fread (buf, 1, range, fp)) != range) - { - PR_fprintf(errorFD, "%s: expected %d bytes, got %d\n", PROGRAM_NAME, - range, num); - errorCount++; - exit (ERRX); - } - - md5 = MD5_NewContext(); - sha1 = SHA1_NewContext(); - - if (md5 == NULL || sha1 == NULL) - { - PR_fprintf(errorFD, "%s: can't generate digest context\n", PROGRAM_NAME); - errorCount++; - exit (ERRX); - } - - MD5_Begin (md5); - SHA1_Begin (sha1); - - MD5_Update (md5, buf, range); - SHA1_Update (sha1, buf, range); - - MD5_End (md5, dig->md5, &md5_length, MD5_LENGTH); - SHA1_End (sha1, dig->sha1, &sha1_length, SHA1_LENGTH); - - MD5_DestroyContext (md5, PR_TRUE); - SHA1_DestroyContext (sha1, PR_TRUE); - - PORT_Free (buf); - - return 0; -} - -static void SignOut (void *arg, const char *buf, unsigned long len) -{ - fwrite (buf, len, 1, (FILE *) arg); -} |