mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 00:55:37 +00:00
c33352aa54
jarver.c (bug 337361). Patch contributed by ehsan.akhgari@gmail.com
362 lines
8.2 KiB
C
362 lines
8.2 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* 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 the Initial Developer are Copyright (C) 1994-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
int status = JAR_ERR_GENERAL;
|
|
JAR_FILE sf_fp;
|
|
JAR_FILE out_fp;
|
|
|
|
CERTCertDBHandle *certdb;
|
|
void *keydb;
|
|
|
|
CERTCertificate *cert;
|
|
|
|
if (PORT_Strlen (sf) < 5)
|
|
{
|
|
return JAR_ERR_GENERAL;
|
|
}
|
|
|
|
/* open cert and key databases */
|
|
|
|
certdb = JAR_open_database();
|
|
if (certdb == NULL)
|
|
return JAR_ERR_GENERAL;
|
|
|
|
keydb = jar_open_key_database();
|
|
if (keydb == NULL)
|
|
{
|
|
JAR_close_database(certdb);
|
|
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;
|
|
}
|