/* * 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. */ /* * JARJART * * JAR functions used by Jartool */ /* This allows manifest files above 64k to be processed on non-win16 platforms */ #include "jar.h" #include "jarint.h" #include "jarjart.h" #include "blapi.h" /* JAR is supposed to be above the line!! */ #include "pk11func.h" /* PK11 wrapper funcs are all above the line. */ #include "certdb.h" /* from certdb.h */ #define CERTDB_USER (1<<6) /* * S O B _ l i s t _ c e r t s * * Return a list of newline separated certificate nicknames * (this function used by the Jartool) * */ static SECStatus jar_list_cert_callback (CERTCertificate *cert, SECItem *k, void *data) { char *name; char **ugly_list; int trusted; ugly_list = (char **) data; if (cert) { name = cert->nickname; trusted = cert->trust->objectSigningFlags & CERTDB_USER; /* Add this name or email to list */ if (name && trusted) { *ugly_list = (char*)PORT_Realloc (*ugly_list, PORT_Strlen (*ugly_list) + PORT_Strlen (name) + 2); if (*ugly_list) { if (**ugly_list) PORT_Strcat (*ugly_list, "\n"); PORT_Strcat (*ugly_list, name); } } } return (SECSuccess); } /* * S O B _ J A R _ l i s t _ c e r t s * * Return a linfeed separated ascii list of certificate * nicknames for the Jartool. * */ char *JAR_JAR_list_certs (void) { SECStatus status = SECFailure; CERTCertDBHandle *certdb; CERTCertList *certs; CERTCertListNode *node; char *ugly_list; certdb = JAR_open_database(); /* a little something */ ugly_list = (char*)PORT_ZAlloc (16); if (ugly_list) { *ugly_list = 0; certs = PK11_ListCerts(PK11CertListUnique, NULL/* pwarg*/); if (certs) { for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); node = CERT_LIST_NEXT(node)) { jar_list_cert_callback(node->cert, NULL, (void *)&ugly_list); } CERT_DestroyCertList(certs); status = SECSuccess; } } JAR_close_database (certdb); return (status != SECSuccess) ? NULL : ugly_list; } int JAR_JAR_validate_archive (char *filename) { JAR *jar; int status = -1; jar = JAR_new(); if (jar) { status = JAR_pass_archive (jar, jarArchGuess, filename, ""); if (status == 0) status = jar->valid; JAR_destroy (jar); } return status; } char *JAR_JAR_get_error (int status) { return JAR_get_error (status); } /* * S O B _ J A R _ h a s h * * Hash algorithm interface for use by the Jartool. Since we really * don't know the private sizes of the context, and Java does need to * know this number, allocate 512 bytes for it. * * In april 1997 hashes in this file were changed to call PKCS11, * as FIPS requires that when a smartcard has failed validation, * hashes are not to be performed. But because of the difficulty of * preserving pointer context between calls to the JAR_JAR hashing * functions, the hash routines are called directly, though after * checking to see if hashing is allowed. * */ void *JAR_JAR_new_hash (int alg) { void *context; MD5Context *md5; SHA1Context *sha1; /* this is a hack because this whole PORT_ZAlloc stuff looks scary */ if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1)) return NULL; context = PORT_ZAlloc (512); if (context) { switch (alg) { case 1: /* MD5 */ md5 = (MD5Context *) context; MD5_Begin (md5); break; case 2: /* SHA1 */ sha1 = (SHA1Context *) context; SHA1_Begin (sha1); break; } } return context; } void *JAR_JAR_hash (int alg, void *cookie, int length, void *data) { MD5Context *md5; SHA1Context *sha1; /* this is a hack because this whole PORT_ZAlloc stuff looks scary */ if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1)) return NULL; if (length > 0) { switch (alg) { case 1: /* MD5 */ md5 = (MD5Context *) cookie; MD5_Update (md5, (unsigned char*)data, length); break; case 2: /* SHA1 */ sha1 = (SHA1Context *) cookie; SHA1_Update (sha1, (unsigned char*)data, length); break; } } return cookie; } void *JAR_JAR_end_hash (int alg, void *cookie) { int length; unsigned char *data; char *ascii; MD5Context *md5; SHA1Context *sha1; unsigned int md5_length; unsigned char md5_digest [MD5_LENGTH]; unsigned int sha1_length; unsigned char sha1_digest [SHA1_LENGTH]; /* this is a hack because this whole PORT_ZAlloc stuff looks scary */ if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1)) return NULL; switch (alg) { case 1: /* MD5 */ md5 = (MD5Context *) cookie; MD5_End (md5, md5_digest, &md5_length, MD5_LENGTH); /* MD5_DestroyContext (md5, PR_TRUE); */ data = md5_digest; length = md5_length; break; case 2: /* SHA1 */ sha1 = (SHA1Context *) cookie; SHA1_End (sha1, sha1_digest, &sha1_length, SHA1_LENGTH); /* SHA1_DestroyContext (sha1, PR_TRUE); */ data = sha1_digest; length = sha1_length; break; default: return NULL; } /* Instead of destroy context, since we created it */ /* PORT_Free (cookie); */ ascii = BTOA_DataToAscii(data, length); return ascii ? PORT_Strdup (ascii) : NULL; } /* * S O B _ J A R _ s i g n _ a r c h i v e * * A simple API to sign a JAR archive. * */ int JAR_JAR_sign_archive (char *nickname, char *password, char *sf, char *outsig) { char *out_fn; int status = JAR_ERR_GENERAL; JAR_FILE sf_fp; JAR_FILE out_fp; CERTCertDBHandle *certdb; void *keydb; CERTCertificate *cert; /* open cert and key databases */ certdb = JAR_open_database(); if (certdb == NULL) return JAR_ERR_GENERAL; keydb = jar_open_key_database(); if (keydb == NULL) return JAR_ERR_GENERAL; out_fn = PORT_Strdup (sf); if (out_fn == NULL || PORT_Strlen (sf) < 5) return JAR_ERR_GENERAL; sf_fp = JAR_FOPEN (sf, "rb"); out_fp = JAR_FOPEN (outsig, "wb"); cert = CERT_FindCertByNickname (certdb, nickname); if (cert && sf_fp && out_fp) { status = jar_create_pk7 (certdb, keydb, cert, password, sf_fp, out_fp); } /* remove password from prying eyes */ PORT_Memset (password, 0, PORT_Strlen (password)); JAR_FCLOSE (sf_fp); JAR_FCLOSE (out_fp); JAR_close_database (certdb); jar_close_key_database (keydb); return status; }