summaryrefslogtreecommitdiff
path: root/security/nss/lib/jar
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
committerrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
commit9502869e82d4f3ce26b292263e1c626dca3a34f3 (patch)
tree4d0f8ab157505b57c13a5e2bdf979560ab751527 /security/nss/lib/jar
parent222a52dab759085f56dcb6588b69a6a937d82aa2 (diff)
downloadnss-hg-9502869e82d4f3ce26b292263e1c626dca3a34f3.tar.gz
Initial NSS Open Source checkin
Diffstat (limited to 'security/nss/lib/jar')
-rw-r--r--security/nss/lib/jar/Makefile39
-rw-r--r--security/nss/lib/jar/config.mk44
-rw-r--r--security/nss/lib/jar/jar-ds.c70
-rw-r--r--security/nss/lib/jar/jar-ds.h106
-rw-r--r--security/nss/lib/jar/jar.c833
-rw-r--r--security/nss/lib/jar/jar.h477
-rw-r--r--security/nss/lib/jar/jarevil.c571
-rw-r--r--security/nss/lib/jar/jarevil.h76
-rw-r--r--security/nss/lib/jar/jarfile.c1149
-rw-r--r--security/nss/lib/jar/jarfile.h114
-rw-r--r--security/nss/lib/jar/jarint.c81
-rw-r--r--security/nss/lib/jar/jarint.h116
-rw-r--r--security/nss/lib/jar/jarjart.c354
-rw-r--r--security/nss/lib/jar/jarjart.h72
-rw-r--r--security/nss/lib/jar/jarnav.c107
-rw-r--r--security/nss/lib/jar/jarsign.c376
-rw-r--r--security/nss/lib/jar/jarver.c2029
-rw-r--r--security/nss/lib/jar/jzconf.h190
-rw-r--r--security/nss/lib/jar/jzlib.h892
-rw-r--r--security/nss/lib/jar/manifest.mn51
20 files changed, 7747 insertions, 0 deletions
diff --git a/security/nss/lib/jar/Makefile b/security/nss/lib/jar/Makefile
new file mode 100644
index 000000000..063e5daf7
--- /dev/null
+++ b/security/nss/lib/jar/Makefile
@@ -0,0 +1,39 @@
+#! gmake
+#
+# 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 manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+include config.mk
+include $(CORE_DEPTH)/coreconf/rules.mk
+
diff --git a/security/nss/lib/jar/config.mk b/security/nss/lib/jar/config.mk
new file mode 100644
index 000000000..a73a1086e
--- /dev/null
+++ b/security/nss/lib/jar/config.mk
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PURE_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/lib/jar/jar-ds.c b/security/nss/lib/jar/jar-ds.c
new file mode 100644
index 000000000..f5a40cad5
--- /dev/null
+++ b/security/nss/lib/jar/jar-ds.c
@@ -0,0 +1,70 @@
+/*
+ * 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 "jar.h"
+
+/* These are old DS_* routines renamed to ZZ_* */
+
+ZZList *ZZ_NewList()
+ {
+ ZZList *list;
+
+ list = (ZZList *) PORT_ZAlloc (sizeof (ZZList));
+
+ if (list)
+ ZZ_InitList (list);
+
+ return list;
+ }
+
+ZZLink *ZZ_NewLink (JAR_Item *thing)
+ {
+ ZZLink *link;
+
+ link = (ZZLink *) PORT_ZAlloc (sizeof (ZZLink));
+
+ if (link)
+ link->thing = thing;
+
+ return link;
+ }
+
+void ZZ_DestroyLink (ZZLink *link)
+ {
+ PORT_Free (link);
+ }
+
+void ZZ_DestroyList (ZZList *list)
+ {
+ PORT_Free (list);
+ }
diff --git a/security/nss/lib/jar/jar-ds.h b/security/nss/lib/jar/jar-ds.h
new file mode 100644
index 000000000..36716d97c
--- /dev/null
+++ b/security/nss/lib/jar/jar-ds.h
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#ifndef __JAR_DS_h_
+#define __JAR_DS_h_
+
+/* Typedefs */
+typedef struct ZZLinkStr ZZLink;
+typedef struct ZZListStr ZZList;
+
+/*
+** Circular linked list. Each link contains a pointer to the object that
+** is actually in the list.
+*/
+struct ZZLinkStr
+{
+ ZZLink *next;
+ ZZLink *prev;
+ JAR_Item *thing;
+};
+
+struct ZZListStr
+{
+ ZZLink link;
+};
+
+#define ZZ_InitList(lst) \
+{ \
+ (lst)->link.next = &(lst)->link; \
+ (lst)->link.prev = &(lst)->link; \
+ (lst)->link.thing = 0; \
+}
+
+#define ZZ_ListEmpty(lst) \
+ ((lst)->link.next == &(lst)->link)
+
+#define ZZ_ListHead(lst) \
+ ((lst)->link.next)
+
+#define ZZ_ListTail(lst) \
+ ((lst)->link.prev)
+
+#define ZZ_ListIterDone(lst,lnk) \
+ ((lnk) == &(lst)->link)
+
+#define ZZ_AppendLink(lst,lnk) \
+{ \
+ (lnk)->next = &(lst)->link; \
+ (lnk)->prev = (lst)->link.prev; \
+ (lst)->link.prev->next = (lnk); \
+ (lst)->link.prev = (lnk); \
+}
+
+#define ZZ_InsertLink(lst,lnk) \
+{ \
+ (lnk)->next = (lst)->link.next; \
+ (lnk)->prev = &(lst)->link; \
+ (lst)->link.next->prev = (lnk); \
+ (lst)->link.next = (lnk); \
+}
+
+#define ZZ_RemoveLink(lnk) \
+{ \
+ (lnk)->next->prev = (lnk)->prev; \
+ (lnk)->prev->next = (lnk)->next; \
+ (lnk)->next = 0; \
+ (lnk)->prev = 0; \
+}
+
+extern ZZLink *ZZ_NewLink (JAR_Item *thing);
+extern void ZZ_DestroyLink (ZZLink *link);
+extern ZZList *ZZ_NewList (void);
+extern void ZZ_DestroyList (ZZList *list);
+
+
+#endif /* __JAR_DS_h_ */
diff --git a/security/nss/lib/jar/jar.c b/security/nss/lib/jar/jar.c
new file mode 100644
index 000000000..99ba4ca0b
--- /dev/null
+++ b/security/nss/lib/jar/jar.c
@@ -0,0 +1,833 @@
+/*
+ * 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.
+ */
+
+/*
+ * JAR.C
+ *
+ * Jarnature.
+ * Routines common to signing and validating.
+ *
+ */
+
+#include "jar.h"
+#include "jarint.h"
+
+static void jar_destroy_list (ZZList *list);
+
+static int jar_find_first_cert
+ (JAR_Signer *signer, int type, JAR_Item **it);
+
+/*
+ * J A R _ n e w
+ *
+ * Create a new instantiation of a manifest representation.
+ * Use this as a token to any calls to this API.
+ *
+ */
+
+JAR *JAR_new (void)
+ {
+ JAR *jar;
+
+ if ((jar = (JAR*)PORT_ZAlloc (sizeof (JAR))) == NULL)
+ goto loser;
+
+ if ((jar->manifest = ZZ_NewList()) == NULL)
+ goto loser;
+
+ if ((jar->hashes = ZZ_NewList()) == NULL)
+ goto loser;
+
+ if ((jar->phy = ZZ_NewList()) == NULL)
+ goto loser;
+
+ if ((jar->metainfo = ZZ_NewList()) == NULL)
+ goto loser;
+
+ if ((jar->signers = ZZ_NewList()) == NULL)
+ goto loser;
+
+ return jar;
+
+loser:
+
+ if (jar)
+ {
+ if (jar->manifest)
+ ZZ_DestroyList (jar->manifest);
+
+ if (jar->hashes)
+ ZZ_DestroyList (jar->hashes);
+
+ if (jar->phy)
+ ZZ_DestroyList (jar->phy);
+
+ if (jar->metainfo)
+ ZZ_DestroyList (jar->metainfo);
+
+ if (jar->signers)
+ ZZ_DestroyList (jar->signers);
+
+ PORT_Free (jar);
+ }
+
+ return NULL;
+ }
+
+/*
+ * J A R _ d e s t r o y
+ *
+ * Godzilla.
+ *
+ */
+
+void PR_CALLBACK JAR_destroy (JAR *jar)
+ {
+ JAR *z;
+
+ PORT_Assert( jar != NULL );
+
+ if (jar == NULL)
+ return;
+
+ if (jar->fp) JAR_FCLOSE ((PRFileDesc*)jar->fp);
+
+ if (jar->url) PORT_Free (jar->url);
+ if (jar->filename) PORT_Free (jar->filename);
+
+ /* Free the linked list elements */
+
+ jar_destroy_list (jar->manifest);
+ ZZ_DestroyList (jar->manifest);
+
+ jar_destroy_list (jar->hashes);
+ ZZ_DestroyList (jar->hashes);
+
+ jar_destroy_list (jar->phy);
+ ZZ_DestroyList (jar->phy);
+
+ jar_destroy_list (jar->metainfo);
+ ZZ_DestroyList (jar->metainfo);
+
+ jar_destroy_list (jar->signers);
+ ZZ_DestroyList (jar->signers);
+
+ PORT_Free (jar);
+ }
+
+static void jar_destroy_list (ZZList *list)
+ {
+ ZZLink *link, *oldlink;
+
+ JAR_Item *it;
+
+ JAR_Physical *phy;
+ JAR_Digest *dig;
+ JAR_Cert *fing;
+ JAR_Metainfo *met;
+ JAR_Signer *signer;
+
+ if (list && !ZZ_ListEmpty (list))
+ {
+ link = ZZ_ListHead (list);
+
+ while (!ZZ_ListIterDone (list, link))
+ {
+ it = link->thing;
+ if (!it) goto next;
+
+ if (it->pathname) PORT_Free (it->pathname);
+
+ switch (it->type)
+ {
+ case jarTypeMeta:
+
+ met = (JAR_Metainfo *) it->data;
+ if (met)
+ {
+ if (met->header) PORT_Free (met->header);
+ if (met->info) PORT_Free (met->info);
+ PORT_Free (met);
+ }
+ break;
+
+ case jarTypePhy:
+
+ phy = (JAR_Physical *) it->data;
+ if (phy)
+ PORT_Free (phy);
+ break;
+
+ case jarTypeSign:
+
+ fing = (JAR_Cert *) it->data;
+ if (fing)
+ {
+ if (fing->cert)
+ CERT_DestroyCertificate (fing->cert);
+ if (fing->key)
+ PORT_Free (fing->key);
+ PORT_Free (fing);
+ }
+ break;
+
+ case jarTypeSect:
+ case jarTypeMF:
+ case jarTypeSF:
+
+ dig = (JAR_Digest *) it->data;
+ if (dig)
+ {
+ PORT_Free (dig);
+ }
+ break;
+
+ case jarTypeOwner:
+
+ signer = (JAR_Signer *) it->data;
+
+ if (signer)
+ JAR_destroy_signer (signer);
+
+ break;
+
+ default:
+
+ /* PORT_Assert( 1 != 2 ); */
+ break;
+ }
+
+ PORT_Free (it);
+
+ next:
+
+ oldlink = link;
+ link = link->next;
+
+ ZZ_DestroyLink (oldlink);
+ }
+ }
+ }
+
+/*
+ * J A R _ g e t _ m e t a i n f o
+ *
+ * Retrieve meta information from the manifest file.
+ * It doesn't matter whether it's from .MF or .SF, does it?
+ *
+ */
+
+int JAR_get_metainfo
+ (JAR *jar, char *name, char *header, void **info, unsigned long *length)
+ {
+ JAR_Item *it;
+
+ ZZLink *link;
+ ZZList *list;
+
+ JAR_Metainfo *met;
+
+ PORT_Assert( jar != NULL && header != NULL );
+
+ if (jar == NULL || header == NULL)
+ return JAR_ERR_PNF;
+
+ list = jar->metainfo;
+
+ if (ZZ_ListEmpty (list))
+ return JAR_ERR_PNF;
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ it = link->thing;
+ if (it->type == jarTypeMeta)
+ {
+ if ((name && !it->pathname) || (!name && it->pathname))
+ continue;
+
+ if (name && it->pathname && strcmp (it->pathname, name))
+ continue;
+
+ met = (JAR_Metainfo *) it->data;
+
+ if (!PORT_Strcasecmp (met->header, header))
+ {
+ *info = PORT_Strdup (met->info);
+ *length = PORT_Strlen (met->info);
+ return 0;
+ }
+ }
+ }
+
+ return JAR_ERR_PNF;
+ }
+
+/*
+ * J A R _ f i n d
+ *
+ * Establish the search pattern for use
+ * by JAR_find_next, to traverse the filenames
+ * or certificates in the JAR structure.
+ *
+ * See jar.h for a description on how to use.
+ *
+ */
+
+JAR_Context *JAR_find (JAR *jar, char *pattern, jarType type)
+ {
+ JAR_Context *ctx;
+
+ PORT_Assert( jar != NULL );
+
+ if (!jar)
+ return NULL;
+
+ ctx = (JAR_Context *) PORT_ZAlloc (sizeof (JAR_Context));
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->jar = jar;
+
+ if (pattern)
+ {
+ if ((ctx->pattern = PORT_Strdup (pattern)) == NULL)
+ {
+ PORT_Free (ctx);
+ return NULL;
+ }
+ }
+
+ ctx->finding = type;
+
+ switch (type)
+ {
+ case jarTypeMF: ctx->next = ZZ_ListHead (jar->hashes);
+ break;
+
+ case jarTypeSF:
+ case jarTypeSign: ctx->next = NULL;
+ ctx->nextsign = ZZ_ListHead (jar->signers);
+ break;
+
+ case jarTypeSect: ctx->next = ZZ_ListHead (jar->manifest);
+ break;
+
+ case jarTypePhy: ctx->next = ZZ_ListHead (jar->phy);
+ break;
+
+ case jarTypeOwner: if (jar->signers)
+ ctx->next = ZZ_ListHead (jar->signers);
+ else
+ ctx->next = NULL;
+ break;
+
+ case jarTypeMeta: ctx->next = ZZ_ListHead (jar->metainfo);
+ break;
+
+ default: PORT_Assert( 1 != 2);
+ break;
+ }
+
+ return ctx;
+ }
+
+/*
+ * J A R _ f i n d _ e n d
+ *
+ * Destroy the find iterator context.
+ *
+ */
+
+void JAR_find_end (JAR_Context *ctx)
+ {
+ PORT_Assert( ctx != NULL );
+
+ if (ctx)
+ {
+ if (ctx->pattern)
+ PORT_Free (ctx->pattern);
+ PORT_Free (ctx);
+ }
+ }
+
+/*
+ * J A R _ f i n d _ n e x t
+ *
+ * Return the next item of the given type
+ * from one of the JAR linked lists.
+ *
+ */
+
+int JAR_find_next (JAR_Context *ctx, JAR_Item **it)
+ {
+ JAR *jar;
+ ZZList *list;
+
+ int finding;
+
+ JAR_Signer *signer = NULL;
+
+ PORT_Assert( ctx != NULL );
+ PORT_Assert( ctx->jar != NULL );
+
+ jar = ctx->jar;
+
+ /* Internally, convert jarTypeSign to jarTypeSF, and return
+ the actual attached certificate later */
+
+ finding = (ctx->finding == jarTypeSign) ? jarTypeSF : ctx->finding;
+
+ if (ctx->nextsign)
+ {
+ if (ZZ_ListIterDone (jar->signers, ctx->nextsign))
+ {
+ *it = NULL;
+ return -1;
+ }
+ PORT_Assert (ctx->nextsign->thing != NULL);
+ signer = (JAR_Signer*)ctx->nextsign->thing->data;
+ }
+
+
+ /* Find out which linked list to traverse. Then if
+ necessary, advance to the next linked list. */
+
+ while (1)
+ {
+ switch (finding)
+ {
+ case jarTypeSign: /* not any more */
+ PORT_Assert( finding != jarTypeSign );
+ list = signer->certs;
+ break;
+
+ case jarTypeSect: list = jar->manifest;
+ break;
+
+ case jarTypePhy: list = jar->phy;
+ break;
+
+ case jarTypeSF: /* signer, not jar */
+ PORT_Assert( signer != NULL );
+ list = signer->sf;
+ break;
+
+ case jarTypeMF: list = jar->hashes;
+ break;
+
+ case jarTypeOwner: list = jar->signers;
+ break;
+
+ case jarTypeMeta: list = jar->metainfo;
+ break;
+
+ default: PORT_Assert( 1 != 2 );
+ break;
+ }
+
+ if (list == NULL)
+ {
+ *it = NULL;
+ return -1;
+ }
+
+ /* When looping over lists of lists, advance
+ to the next signer. This is done when multiple
+ signers are possible. */
+
+ if (ZZ_ListIterDone (list, ctx->next))
+ {
+ if (ctx->nextsign && jar->signers)
+ {
+ ctx->nextsign = ctx->nextsign->next;
+ if (!ZZ_ListIterDone (jar->signers, ctx->nextsign))
+ {
+ PORT_Assert (ctx->nextsign->thing != NULL);
+
+ signer = (JAR_Signer*)ctx->nextsign->thing->data;
+ PORT_Assert( signer != NULL );
+
+ ctx->next = NULL;
+ continue;
+ }
+ }
+ *it = NULL;
+ return -1;
+ }
+
+ /* if the signer changed, still need to fill
+ in the "next" link */
+
+ if (ctx->nextsign && ctx->next == NULL)
+ {
+ switch (finding)
+ {
+ case jarTypeSF:
+
+ ctx->next = ZZ_ListHead (signer->sf);
+ break;
+
+ case jarTypeSign:
+
+ ctx->next = ZZ_ListHead (signer->certs);
+ break;
+ }
+ }
+
+ PORT_Assert( ctx->next != NULL );
+
+
+ while (!ZZ_ListIterDone (list, ctx->next))
+ {
+ *it = ctx->next->thing;
+ ctx->next = ctx->next->next;
+
+ if (!it || !*it || (*it)->type != finding)
+ continue;
+
+ if (ctx->pattern && *ctx->pattern)
+ {
+ if (PORT_Strcmp ((*it)->pathname, ctx->pattern))
+ continue;
+ }
+
+ /* We have a valid match. If this is a jarTypeSign
+ return the certificate instead.. */
+
+ if (ctx->finding == jarTypeSign)
+ {
+ JAR_Item *itt;
+
+ /* just the first one for now */
+ if (jar_find_first_cert (signer, jarTypeSign, &itt) >= 0)
+ {
+ *it = itt;
+ return 0;
+ }
+
+ continue;
+ }
+
+ return 0;
+ }
+
+ } /* end while */
+ }
+
+static int jar_find_first_cert
+ (JAR_Signer *signer, int type, JAR_Item **it)
+ {
+ ZZLink *link;
+ ZZList *list;
+
+ int status = JAR_ERR_PNF;
+
+ list = signer->certs;
+
+ *it = NULL;
+
+ if (ZZ_ListEmpty (list))
+ {
+ /* empty list */
+ return JAR_ERR_PNF;
+ }
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ if (link->thing->type == type)
+ {
+ *it = link->thing;
+ status = 0;
+ break;
+ }
+ }
+
+ return status;
+ }
+
+JAR_Signer *JAR_new_signer (void)
+ {
+ JAR_Signer *signer;
+
+ signer = (JAR_Signer *) PORT_ZAlloc (sizeof (JAR_Signer));
+
+ if (signer == NULL)
+ goto loser;
+
+
+ /* certs */
+ signer->certs = ZZ_NewList();
+
+ if (signer->certs == NULL)
+ goto loser;
+
+
+ /* sf */
+ signer->sf = ZZ_NewList();
+
+ if (signer->sf == NULL)
+ goto loser;
+
+
+ return signer;
+
+
+loser:
+
+ if (signer)
+ {
+ if (signer->certs)
+ ZZ_DestroyList (signer->certs);
+
+ if (signer->sf)
+ ZZ_DestroyList (signer->sf);
+
+ PORT_Free (signer);
+ }
+
+ return NULL;
+ }
+
+void JAR_destroy_signer (JAR_Signer *signer)
+ {
+ if (signer)
+ {
+ if (signer->owner) PORT_Free (signer->owner);
+ if (signer->digest) PORT_Free (signer->digest);
+
+ jar_destroy_list (signer->sf);
+ ZZ_DestroyList (signer->sf);
+
+ jar_destroy_list (signer->certs);
+ ZZ_DestroyList (signer->certs);
+
+ PORT_Free (signer);
+ }
+ }
+
+JAR_Signer *jar_get_signer (JAR *jar, char *basename)
+ {
+ JAR_Item *it;
+ JAR_Context *ctx;
+
+ JAR_Signer *candidate;
+ JAR_Signer *signer = NULL;
+
+ ctx = JAR_find (jar, NULL, jarTypeOwner);
+
+ if (ctx == NULL)
+ return NULL;
+
+ while (JAR_find_next (ctx, &it) >= 0)
+ {
+ candidate = (JAR_Signer *) it->data;
+ if (*basename == '*' || !PORT_Strcmp (candidate->owner, basename))
+ {
+ signer = candidate;
+ break;
+ }
+ }
+
+ JAR_find_end (ctx);
+
+ return signer;
+ }
+
+/*
+ * J A R _ g e t _ f i l e n a m e
+ *
+ * Returns the filename associated with
+ * a JAR structure.
+ *
+ */
+
+char *JAR_get_filename (JAR *jar)
+ {
+ return jar->filename;
+ }
+
+/*
+ * J A R _ g e t _ u r l
+ *
+ * Returns the URL associated with
+ * a JAR structure. Nobody really uses this now.
+ *
+ */
+
+char *JAR_get_url (JAR *jar)
+ {
+ return jar->url;
+ }
+
+/*
+ * J A R _ s e t _ c a l l b a c k
+ *
+ * Register some manner of callback function for this jar.
+ *
+ */
+
+int JAR_set_callback (int type, JAR *jar,
+ int (*fn) (int status, JAR *jar,
+ const char *metafile, char *pathname, char *errortext))
+ {
+ if (type == JAR_CB_SIGNAL)
+ {
+ jar->signal = fn;
+ return 0;
+ }
+ else
+ return -1;
+ }
+
+/*
+ * Callbacks
+ *
+ */
+
+/* To return an error string */
+char *(*jar_fn_GetString) (int) = NULL;
+
+/* To return an MWContext for Java */
+void *(*jar_fn_FindSomeContext) (void) = NULL;
+
+/* To fabricate an MWContext for FE_GetPassword */
+void *(*jar_fn_GetInitContext) (void) = NULL;
+
+void
+JAR_init_callbacks
+ (
+ char *(*string_cb)(int),
+ void *(*find_cx)(void),
+ void *(*init_cx)(void)
+ )
+ {
+ jar_fn_GetString = string_cb;
+ jar_fn_FindSomeContext = find_cx;
+ jar_fn_GetInitContext = init_cx;
+ }
+
+/*
+ * J A R _ g e t _ e r r o r
+ *
+ * This is provided to map internal JAR errors to strings for
+ * the Java console. Also, a DLL may call this function if it does
+ * not have access to the XP_GetString function.
+ *
+ * These strings aren't UI, since they are Java console only.
+ *
+ */
+
+char *JAR_get_error (int status)
+ {
+ char *errstring = NULL;
+
+ switch (status)
+ {
+ case JAR_ERR_GENERAL:
+ errstring = "General JAR file error";
+ break;
+
+ case JAR_ERR_FNF:
+ errstring = "JAR file not found";
+ break;
+
+ case JAR_ERR_CORRUPT:
+ errstring = "Corrupt JAR file";
+ break;
+
+ case JAR_ERR_MEMORY:
+ errstring = "Out of memory";
+ break;
+
+ case JAR_ERR_DISK:
+ errstring = "Disk error (perhaps out of space)";
+ break;
+
+ case JAR_ERR_ORDER:
+ errstring = "Inconsistent files in META-INF directory";
+ break;
+
+ case JAR_ERR_SIG:
+ errstring = "Invalid digital signature file";
+ break;
+
+ case JAR_ERR_METADATA:
+ errstring = "JAR metadata failed verification";
+ break;
+
+ case JAR_ERR_ENTRY:
+ errstring = "No Manifest entry for this JAR entry";
+ break;
+
+ case JAR_ERR_HASH:
+ errstring = "Invalid Hash of this JAR entry";
+ break;
+
+ case JAR_ERR_PK7:
+ errstring = "Strange PKCS7 or RSA failure";
+ break;
+
+ case JAR_ERR_PNF:
+ errstring = "Path not found inside JAR file";
+ break;
+
+ default:
+ if (jar_fn_GetString)
+ {
+ errstring = jar_fn_GetString (status);
+ }
+ else
+ {
+ /* this is not a normal situation, and would only be
+ called in cases of improper initialization */
+
+ char *err;
+
+ err = (char*)PORT_Alloc (40);
+ if (err)
+ PR_snprintf (err, 39, "Error %d\n", status);
+ else
+ err = "Error! Bad! Out of memory!";
+
+ return err;
+ }
+ break;
+ }
+
+ return errstring;
+ }
diff --git a/security/nss/lib/jar/jar.h b/security/nss/lib/jar/jar.h
new file mode 100644
index 000000000..1b21e6292
--- /dev/null
+++ b/security/nss/lib/jar/jar.h
@@ -0,0 +1,477 @@
+/*
+ * 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.
+ */
+
+#ifndef __JAR_h_
+#define __JAR_h_
+
+/*
+ * In general, any functions that return pointers
+ * have memory owned by the caller.
+ *
+ */
+
+/* security includes */
+#include "cert.h"
+
+/* nspr 2.0 includes */
+#include "prio.h"
+
+#ifndef ZHUGEP
+#ifdef XP_WIN16
+#define ZHUGEP __huge
+#else
+#define ZHUGEP
+#endif
+#endif
+
+#include "stdio.h"
+
+/* various types */
+
+typedef enum
+ {
+ jarTypeMF = 2,
+ jarTypeSF = 3,
+ jarTypeMeta = 6,
+ jarTypePhy = 7,
+ jarTypeSign = 10,
+ jarTypeSect = 11,
+ jarTypeOwner = 13
+ }
+jarType;
+
+/* void data in ZZList's contain JAR_Item type */
+
+typedef struct JAR_Item_
+ {
+ char *pathname; /* relative. inside zip file */
+ jarType type; /* various types */
+ size_t size; /* size of data below */
+ void *data; /* totally opaque */
+ }
+JAR_Item;
+
+
+/* hashes */
+
+typedef enum
+ {
+ jarHashNone = 0,
+ jarHashBad = 1,
+ jarHashPresent = 2
+ }
+jarHash;
+
+typedef struct JAR_Digest_
+ {
+ jarHash md5_status;
+ unsigned char md5 [MD5_LENGTH];
+ jarHash sha1_status;
+ unsigned char sha1 [SHA1_LENGTH];
+ }
+JAR_Digest;
+
+
+/* physical archive formats */
+
+typedef enum
+ {
+ jarArchGuess = 0,
+ jarArchNone = 1,
+ jarArchZip = 2,
+ jarArchTar = 3
+ }
+jarArch;
+
+
+#include "jar-ds.h"
+
+/* jar object */
+
+typedef struct JAR_
+ {
+ jarArch format; /* physical archive format */
+ char *url; /* Where it came from */
+ char *filename; /* Disk location */
+ FILE *fp; /* For multiple extractions */ /* JAR_FILE */
+
+ /* various linked lists */
+
+ ZZList *manifest; /* Digests of MF sections */
+ ZZList *hashes; /* Digests of actual signed files */
+ ZZList *phy; /* Physical layout of JAR file */
+ ZZList *metainfo; /* Global metainfo */
+
+ JAR_Digest *globalmeta; /* digest of .MF global portion */
+
+ /* Below will change to a linked list to support multiple sigs */
+
+ int pkcs7; /* Enforced opaqueness */
+ int valid; /* PKCS7 signature validated */
+
+ ZZList *signers; /* the above, per signer */
+
+ /* Window context, very necessary for PKCS11 now */
+
+ void *mw; /* MWContext window context */
+
+ /* Signal callback function */
+
+ int (*signal) (int status, struct JAR_ *jar,
+ const char *metafile, char *pathname, char *errorstring);
+ }
+JAR;
+
+
+/*
+ * Iterator
+ *
+ * Context for iterative operations. Certain operations
+ * require iterating multiple linked lists because of
+ * multiple signers. "nextsign" is used for this purpose.
+ *
+ */
+
+typedef struct JAR_Context_
+ {
+ JAR *jar; /* Jar we are searching */
+ char *pattern; /* Regular expression */
+ jarType finding; /* Type of item to find */
+ ZZLink *next; /* Next item in find */
+ ZZLink *nextsign; /* Next signer, sometimes */
+ }
+JAR_Context;
+
+typedef struct JAR_Signer_
+ {
+ int pkcs7; /* Enforced opaqueness */
+ int valid; /* PKCS7 signature validated */
+ char *owner; /* name of .RSA file */
+ JAR_Digest *digest; /* of .SF file */
+ ZZList *sf; /* Linked list of .SF file contents */
+ ZZList *certs; /* Signing information */
+ }
+JAR_Signer;
+
+
+/* Meta informaton, or "policy", from the manifest file.
+ Right now just one tuple per JAR_Item. */
+
+typedef struct JAR_Metainfo_
+ {
+ char *header;
+ char *info;
+ }
+JAR_Metainfo;
+
+/* This should not be global */
+
+typedef struct JAR_Physical_
+ {
+ unsigned char compression;
+ unsigned long offset;
+ unsigned long length;
+ unsigned long uncompressed_length;
+#ifdef XP_UNIX
+ uint16 mode;
+#endif
+ }
+JAR_Physical;
+
+typedef struct JAR_Cert_
+ {
+ size_t length;
+ void *key;
+ CERTCertificate *cert;
+ }
+JAR_Cert;
+
+
+/* certificate stuff */
+
+typedef enum
+ {
+ jarCertCompany = 1,
+ jarCertCA = 2,
+ jarCertSerial = 3,
+ jarCertExpires = 4,
+ jarCertNickname = 5,
+ jarCertFinger = 6,
+ jarCertJavaHack = 100
+ }
+jarCert;
+
+/* callback types */
+
+#define JAR_CB_SIGNAL 1
+
+
+/*
+ * This is the base for the JAR error codes. It will
+ * change when these are incorporated into allxpstr.c,
+ * but right now they won't let me put them there.
+ *
+ */
+
+#ifndef SEC_ERR_BASE
+#define SEC_ERR_BASE (-0x2000)
+#endif
+
+#define JAR_BASE SEC_ERR_BASE + 300
+
+/* Jar specific error definitions */
+
+#define JAR_ERR_GENERAL (JAR_BASE + 1)
+#define JAR_ERR_FNF (JAR_BASE + 2)
+#define JAR_ERR_CORRUPT (JAR_BASE + 3)
+#define JAR_ERR_MEMORY (JAR_BASE + 4)
+#define JAR_ERR_DISK (JAR_BASE + 5)
+#define JAR_ERR_ORDER (JAR_BASE + 6)
+#define JAR_ERR_SIG (JAR_BASE + 7)
+#define JAR_ERR_METADATA (JAR_BASE + 8)
+#define JAR_ERR_ENTRY (JAR_BASE + 9)
+#define JAR_ERR_HASH (JAR_BASE + 10)
+#define JAR_ERR_PK7 (JAR_BASE + 11)
+#define JAR_ERR_PNF (JAR_BASE + 12)
+
+
+/*
+ * Birth and death
+ *
+ */
+
+extern JAR *JAR_new (void);
+
+extern void PR_CALLBACK JAR_destroy (JAR *jar);
+
+extern char *JAR_get_error (int status);
+
+extern int JAR_set_callback (int type, JAR *jar,
+ int (*fn) (int status, JAR *jar,
+ const char *metafile, char *pathname, char *errortext));
+
+extern void JAR_init_callbacks
+ ( char *(*string_cb)(int), void *(*find_cx)(void), void *(*init_cx)(void) );
+
+/*
+ * JAR_set_context
+ *
+ * PKCS11 may require a password to be entered by the user
+ * before any crypto routines may be called. This will require
+ * a window context if used from inside Mozilla.
+ *
+ * Call this routine with your context before calling
+ * verifying or signing. If you have no context, call with NULL
+ * and one will be chosen for you.
+ *
+ */
+
+int JAR_set_context (JAR *jar, void /*MWContext*/ *mw);
+
+/*
+ * Iterative operations
+ *
+ * JAR_find sets up for repeated calls with JAR_find_next.
+ * I never liked findfirst and findnext, this is nicer.
+ *
+ * Pattern contains a relative pathname to match inside the
+ * archive. It is currently assumed to be "*".
+ *
+ * To use:
+ *
+ * JAR_Item *item;
+ * JAR_find (jar, "*.class", jarTypeMF);
+ * while (JAR_find_next (jar, &item) >= 0)
+ * { do stuff }
+ *
+ */
+
+
+/* Replacement functions with an external context */
+
+extern JAR_Context *JAR_find (JAR *jar, char *pattern, jarType type);
+
+extern int JAR_find_next (JAR_Context *ctx, JAR_Item **it);
+
+extern void JAR_find_end (JAR_Context *ctx);
+
+
+/*
+ * Function to parse manifest file:
+ *
+ * Many signatures may be attached to a single filename located
+ * inside the zip file. We only support one.
+ *
+ * Several manifests may be included in the zip file.
+ *
+ * You must pass the MANIFEST.MF file before any .SF files.
+ *
+ * Right now this returns a big ole list, privately in the jar structure.
+ * If you need to traverse it, use JAR_find if possible.
+ *
+ * The path is needed to determine what type of binary signature is
+ * being passed, though it is technically not needed for manifest files.
+ *
+ * When parsing an ASCII file, null terminate the ASCII raw_manifest
+ * prior to sending it, and indicate a length of 0. For binary digital
+ * signatures only, indicate the true length of the signature.
+ * (This is legacy behavior.)
+ *
+ * You may free the manifest after parsing it.
+ *
+ */
+
+extern int JAR_parse_manifest
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url);
+
+/*
+ * Verify data (nonstreaming). The signature is actually
+ * checked by JAR_parse_manifest or JAR_pass_archive.
+ *
+ */
+
+extern JAR_Digest * PR_CALLBACK JAR_calculate_digest
+ (void ZHUGEP *data, long length);
+
+extern int PR_CALLBACK JAR_verify_digest
+ (JAR *jar, const char *name, JAR_Digest *dig);
+
+extern int JAR_digest_file (char *filename, JAR_Digest *dig);
+
+/*
+ * Get attribute from certificate:
+ *
+ * Returns any special signed attribute associated with this cert
+ * or signature (passed in "data"). Attributes jarCert*. Most of the time
+ * this will return a zero terminated string.
+ *
+ */
+
+extern int PR_CALLBACK JAR_cert_attribute
+ (JAR *jar, jarCert attrib, long keylen, void *key,
+ void **result, unsigned long *length);
+
+/*
+ * Meta information
+ *
+ * Currently, since this call does not support passing of an owner
+ * (certificate, or physical name of the .sf file), it is restricted to
+ * returning information located in the manifest.mf file.
+ *
+ * Meta information is a name/value pair inside the archive file. Here,
+ * the name is passed in *header and value returned in **info.
+ *
+ * Pass a NULL as the name to retrieve metainfo from the global section.
+ *
+ * Data is returned in **info, of size *length. The return value
+ * will indicate if no data was found.
+ *
+ */
+
+extern int JAR_get_metainfo
+ (JAR *jar, char *name, char *header, void **info, unsigned long *length);
+
+extern char *JAR_get_filename (JAR *jar);
+
+extern char *JAR_get_url (JAR *jar);
+
+/*
+ * Return an HTML mockup of a certificate or signature.
+ *
+ * Returns a zero terminated ascii string
+ * in raw HTML format.
+ *
+ */
+
+extern char *JAR_cert_html
+ (JAR *jar, int style, long keylen, void *key, int *result);
+
+/* save the certificate with this fingerprint in persistent
+ storage, somewhere, for retrieval in a future session when there
+ is no corresponding JAR structure. */
+
+extern int PR_CALLBACK JAR_stash_cert
+ (JAR *jar, long keylen, void *key);
+
+/* retrieve a certificate presumably stashed with the above
+ function, but may be any certificate. Type is &CERTCertificate */
+
+void *JAR_fetch_cert (long length, void *key);
+
+/*
+ * New functions to handle archives alone
+ * (call JAR_new beforehand)
+ *
+ * JAR_pass_archive acts much like parse_manifest. Certificates
+ * are returned in the JAR structure but as opaque data. When calling
+ * JAR_verified_extract you still need to decide which of these
+ * certificates to honor.
+ *
+ * Code to examine a JAR structure is in jarbert.c. You can obtain both
+ * a list of filenames and certificates from traversing the linked list.
+ *
+ */
+
+extern int JAR_pass_archive
+ (JAR *jar, jarArch format, char *filename, const char *url);
+
+/*
+ * Same thing, but don't check signatures
+ */
+extern int JAR_pass_archive_unverified
+ (JAR *jar, jarArch format, char *filename, const char *url);
+
+/*
+ * Extracts a relative pathname from the archive and places it
+ * in the filename specified.
+ *
+ * Call JAR_set_nailed if you want to keep the file descriptors
+ * open between multiple calls to JAR_verify_extract.
+ *
+ */
+
+extern int JAR_verified_extract
+ (JAR *jar, char *path, char *outpath);
+
+/*
+ * JAR_extract does no crypto checking. This can be used if you
+ * need to extract a manifest file or signature, etc.
+ *
+ */
+
+extern int JAR_extract
+ (JAR *jar, char *path, char *outpath);
+
+
+#endif /* __JAR_h_ */
diff --git a/security/nss/lib/jar/jarevil.c b/security/nss/lib/jar/jarevil.c
new file mode 100644
index 000000000..feecd43b0
--- /dev/null
+++ b/security/nss/lib/jar/jarevil.c
@@ -0,0 +1,571 @@
+/*
+ * 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.
+ */
+
+/*
+ * JAREVIL
+ *
+ * Wrappers to callback in the mozilla thread
+ *
+ * Certificate code is unsafe when called outside the
+ * mozilla thread. These functions push an event on the
+ * queue to cause the cert function to run in that thread.
+ *
+ */
+
+#include "jar.h"
+#include "jarint.h"
+
+#include "jarevil.h"
+
+/* from libevent.h */
+#ifdef MOZILLA_CLIENT
+typedef void (*ETVoidPtrFunc) (void * data);
+extern void ET_moz_CallFunction (ETVoidPtrFunc fn, void *data);
+
+extern void *mozilla_event_queue;
+#endif
+
+
+/* Special macros facilitate running on Win 16 */
+#if defined(XP_PC) && !defined(_WIN32) /* then we are win 16 */
+
+ /*
+ * Allocate the data passed to the callback functions from the heap...
+ *
+ * This inter-thread structure cannot reside on a thread stack since the
+ * thread's stack is swapped away with the thread under Win16...
+ */
+
+ #define ALLOC_OR_DEFINE(type, pointer_var_name, out_of_memory_return_value) \
+ type * pointer_var_name = PORT_ZAlloc (sizeof(type)); \
+ do { \
+ if (!pointer_var_name) \
+ return (out_of_memory_return_value); \
+ } while (0) /* and now a semicolon can follow :-) */
+
+ #define FREE_IF_ALLOC_IS_USED(pointer_var_name) PORT_Free(pointer_var_name)
+
+#else /* not win 16... so we can alloc via auto variables */
+
+ #define ALLOC_OR_DEFINE(type, pointer_var_name, out_of_memory_return_value) \
+ type actual_structure_allocated_in_macro; \
+ type * pointer_var_name = &actual_structure_allocated_in_macro; \
+ PORT_Memset (pointer_var_name, 0, sizeof (*pointer_var_name)); \
+ ((void) 0) /* and now a semicolon can follow */
+
+ #define FREE_IF_ALLOC_IS_USED(pointer_var_name) ((void) 0)
+
+#endif /* not Win 16 */
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_encode
+ *
+ * Call SEC_PKCS7Encode inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_encode
+ {
+ int error;
+ SECStatus status;
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7EncoderOutputCallback outputfn;
+ void *outputarg;
+ PK11SymKey *bulkkey;
+ SECKEYGetPasswordKey pwfn;
+ void *pwfnarg;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_encode_fn (void *data)
+ {
+ SECStatus status;
+ struct EVIL_encode *encode_data = (struct EVIL_encode *)data;
+
+ PORT_SetError (encode_data->error);
+
+ status = SEC_PKCS7Encode (encode_data->cinfo, encode_data->outputfn,
+ encode_data->outputarg, encode_data->bulkkey,
+ encode_data->pwfn, encode_data->pwfnarg);
+
+ encode_data->status = status;
+ encode_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+SECStatus jar_moz_encode
+ (
+ SEC_PKCS7ContentInfo *cinfo,
+ SEC_PKCS7EncoderOutputCallback outputfn,
+ void *outputarg,
+ PK11SymKey *bulkkey,
+ SECKEYGetPasswordKey pwfn,
+ void *pwfnarg
+ )
+ {
+ SECStatus ret;
+ ALLOC_OR_DEFINE(struct EVIL_encode, encode_data, SECFailure);
+
+ encode_data->error = PORT_GetError();
+ encode_data->cinfo = cinfo;
+ encode_data->outputfn = outputfn;
+ encode_data->outputarg = outputarg;
+ encode_data->bulkkey = bulkkey;
+ encode_data->pwfn = pwfn;
+ encode_data->pwfnarg = pwfnarg;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_encode_fn, encode_data);
+ else
+ jar_moz_encode_fn (encode_data);
+#else
+ jar_moz_encode_fn (encode_data);
+#endif
+
+ PORT_SetError (encode_data->error);
+ ret = encode_data->status;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(encode_data);
+ return ret;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_verify
+ *
+ * Call SEC_PKCS7VerifyDetachedSignature inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_verify
+ {
+ int error;
+ SECStatus status;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECCertUsage certusage;
+ SECItem *detached_digest;
+ HASH_HashType digest_type;
+ PRBool keepcerts;
+ };
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_verify_fn (void *data)
+ {
+ PRBool result;
+ struct EVIL_verify *verify_data = (struct EVIL_verify *)data;
+
+ PORT_SetError (verify_data->error);
+
+ result = SEC_PKCS7VerifyDetachedSignature
+ (verify_data->cinfo, verify_data->certusage, verify_data->detached_digest,
+ verify_data->digest_type, verify_data->keepcerts);
+
+
+ verify_data->status = result==PR_TRUE ? SECSuccess : SECFailure;
+ verify_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+SECStatus jar_moz_verify
+ (
+ SEC_PKCS7ContentInfo *cinfo,
+ SECCertUsage certusage,
+ SECItem *detached_digest,
+ HASH_HashType digest_type,
+ PRBool keepcerts
+ )
+ {
+ SECStatus ret;
+ ALLOC_OR_DEFINE(struct EVIL_verify, verify_data, SECFailure);
+
+ verify_data->error = PORT_GetError();
+ verify_data->cinfo = cinfo;
+ verify_data->certusage = certusage;
+ verify_data->detached_digest = detached_digest;
+ verify_data->digest_type = digest_type;
+ verify_data->keepcerts = keepcerts;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_verify_fn, verify_data);
+ else
+ jar_moz_verify_fn (verify_data);
+#else
+ jar_moz_verify_fn (verify_data);
+#endif
+
+ PORT_SetError (verify_data->error);
+ ret = verify_data->status;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(verify_data);
+ return ret;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_nickname
+ *
+ * Call CERT_FindCertByNickname inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_nickname
+ {
+ int error;
+ CERTCertDBHandle *certdb;
+ char *nickname;
+ CERTCertificate *cert;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_nickname_fn (void *data)
+ {
+ CERTCertificate *cert;
+ struct EVIL_nickname *nickname_data = (struct EVIL_nickname *)data;
+
+ PORT_SetError (nickname_data->error);
+
+ cert = CERT_FindCertByNickname (nickname_data->certdb, nickname_data->nickname);
+
+ nickname_data->cert = cert;
+ nickname_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+CERTCertificate *jar_moz_nickname (CERTCertDBHandle *certdb, char *nickname)
+ {
+ CERTCertificate *cert;
+ ALLOC_OR_DEFINE(struct EVIL_nickname, nickname_data, NULL );
+
+ nickname_data->error = PORT_GetError();
+ nickname_data->certdb = certdb;
+ nickname_data->nickname = nickname;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_nickname_fn, nickname_data);
+ else
+ jar_moz_nickname_fn (nickname_data);
+#else
+ jar_moz_nickname_fn (nickname_data);
+#endif
+
+ PORT_SetError (nickname_data->error);
+ cert = nickname_data->cert;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(nickname_data);
+ return cert;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_perm
+ *
+ * Call CERT_AddTempCertToPerm inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_perm
+ {
+ int error;
+ SECStatus status;
+ CERTCertificate *cert;
+ char *nickname;
+ CERTCertTrust *trust;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_perm_fn (void *data)
+ {
+ SECStatus status;
+ struct EVIL_perm *perm_data = (struct EVIL_perm *)data;
+
+ PORT_SetError (perm_data->error);
+
+ status = CERT_AddTempCertToPerm (perm_data->cert, perm_data->nickname, perm_data->trust);
+
+ perm_data->status = status;
+ perm_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+SECStatus jar_moz_perm
+ (CERTCertificate *cert, char *nickname, CERTCertTrust *trust)
+ {
+ SECStatus ret;
+ ALLOC_OR_DEFINE(struct EVIL_perm, perm_data, SECFailure);
+
+ perm_data->error = PORT_GetError();
+ perm_data->cert = cert;
+ perm_data->nickname = nickname;
+ perm_data->trust = trust;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_perm_fn, perm_data);
+ else
+ jar_moz_perm_fn (perm_data);
+#else
+ jar_moz_perm_fn (perm_data);
+#endif
+
+ PORT_SetError (perm_data->error);
+ ret = perm_data->status;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(perm_data);
+ return ret;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_certkey
+ *
+ * Call CERT_FindCertByKey inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_certkey
+ {
+ int error;
+ CERTCertificate *cert;
+ CERTCertDBHandle *certdb;
+ SECItem *seckey;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_certkey_fn (void *data)
+ {
+ CERTCertificate *cert;
+ struct EVIL_certkey *certkey_data = (struct EVIL_certkey *)data;
+
+ PORT_SetError (certkey_data->error);
+
+ cert = CERT_FindCertByKey (certkey_data->certdb, certkey_data->seckey);
+
+ certkey_data->cert = cert;
+ certkey_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+CERTCertificate *jar_moz_certkey (CERTCertDBHandle *certdb, SECItem *seckey)
+ {
+ CERTCertificate *cert;
+ ALLOC_OR_DEFINE(struct EVIL_certkey, certkey_data, NULL);
+
+ certkey_data->error = PORT_GetError();
+ certkey_data->certdb = certdb;
+ certkey_data->seckey = seckey;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_certkey_fn, certkey_data);
+ else
+ jar_moz_certkey_fn (certkey_data);
+#else
+ jar_moz_certkey_fn (certkey_data);
+#endif
+
+ PORT_SetError (certkey_data->error);
+ cert = certkey_data->cert;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(certkey_data);
+ return cert;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_issuer
+ *
+ * Call CERT_FindCertIssuer inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_issuer
+ {
+ int error;
+ CERTCertificate *cert;
+ CERTCertificate *issuer;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_issuer_fn (void *data)
+ {
+ CERTCertificate *issuer;
+ struct EVIL_issuer *issuer_data = (struct EVIL_issuer *)data;
+
+ PORT_SetError (issuer_data->error);
+
+ issuer = CERT_FindCertIssuer (issuer_data->cert, PR_Now(),
+ certUsageObjectSigner);
+
+ issuer_data->issuer = issuer;
+ issuer_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+CERTCertificate *jar_moz_issuer (CERTCertificate *cert)
+ {
+ CERTCertificate *issuer_cert;
+ ALLOC_OR_DEFINE(struct EVIL_issuer, issuer_data, NULL);
+
+ issuer_data->error = PORT_GetError();
+ issuer_data->cert = cert;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_issuer_fn, issuer_data);
+ else
+ jar_moz_issuer_fn (issuer_data);
+#else
+ jar_moz_issuer_fn (issuer_data);
+#endif
+
+ PORT_SetError (issuer_data->error);
+ issuer_cert = issuer_data->issuer;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(issuer_data);
+ return issuer_cert;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
+
+/*
+ * JAR_MOZ_dup
+ *
+ * Call CERT_DupCertificate inside
+ * the mozilla thread
+ *
+ */
+
+struct EVIL_dup
+ {
+ int error;
+ CERTCertificate *cert;
+ CERTCertificate *return_cert;
+ };
+
+
+/* This is called inside the mozilla thread */
+
+PR_STATIC_CALLBACK(void) jar_moz_dup_fn (void *data)
+ {
+ CERTCertificate *return_cert;
+ struct EVIL_dup *dup_data = (struct EVIL_dup *)data;
+
+ PORT_SetError (dup_data->error);
+
+ return_cert = CERT_DupCertificate (dup_data->cert);
+
+ dup_data->return_cert = return_cert;
+ dup_data->error = PORT_GetError();
+ }
+
+
+/* Wrapper for the ET_MOZ call */
+
+CERTCertificate *jar_moz_dup (CERTCertificate *cert)
+ {
+ CERTCertificate *dup_cert;
+ ALLOC_OR_DEFINE(struct EVIL_dup, dup_data, NULL);
+
+ dup_data->error = PORT_GetError();
+ dup_data->cert = cert;
+
+ /* Synchronously invoke the callback function on the mozilla thread. */
+#ifdef MOZILLA_CLIENT
+ if (mozilla_event_queue)
+ ET_moz_CallFunction (jar_moz_dup_fn, dup_data);
+ else
+ jar_moz_dup_fn (dup_data);
+#else
+ jar_moz_dup_fn (dup_data);
+#endif
+
+ PORT_SetError (dup_data->error);
+ dup_cert = dup_data->return_cert;
+
+ /* Free the data passed to the callback function... */
+ FREE_IF_ALLOC_IS_USED(dup_data);
+ return dup_cert;
+ }
+
+/* --- --- --- --- --- --- --- --- --- --- --- --- --- */
diff --git a/security/nss/lib/jar/jarevil.h b/security/nss/lib/jar/jarevil.h
new file mode 100644
index 000000000..a7c835e6c
--- /dev/null
+++ b/security/nss/lib/jar/jarevil.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*
+ * jarevil.h
+ *
+ * dot H file for calls to mozilla thread
+ * from within jarver.c
+ *
+ */
+
+#include "certt.h"
+#include "secpkcs7.h"
+
+extern SECStatus jar_moz_encode
+ (
+ SEC_PKCS7ContentInfo *cinfo,
+ SEC_PKCS7EncoderOutputCallback outputfn,
+ void *outputarg,
+ PK11SymKey *bulkkey,
+ SECKEYGetPasswordKey pwfn,
+ void *pwfnarg
+ );
+
+extern SECStatus jar_moz_verify
+ (
+ SEC_PKCS7ContentInfo *cinfo,
+ SECCertUsage certusage,
+ SECItem *detached_digest,
+ HASH_HashType digest_type,
+ PRBool keepcerts
+ );
+
+extern CERTCertificate *jar_moz_nickname
+ (CERTCertDBHandle *certdb, char *nickname);
+
+extern SECStatus jar_moz_perm
+ (CERTCertificate *cert, char *nickname, CERTCertTrust *trust);
+
+extern CERTCertificate *jar_moz_certkey
+ (CERTCertDBHandle *certdb, SECItem *seckey);
+
+extern CERTCertificate *jar_moz_issuer (CERTCertificate *cert);
+
+extern CERTCertificate *jar_moz_dup (CERTCertificate *cert);
+
diff --git a/security/nss/lib/jar/jarfile.c b/security/nss/lib/jar/jarfile.c
new file mode 100644
index 000000000..5f5b0e67f
--- /dev/null
+++ b/security/nss/lib/jar/jarfile.c
@@ -0,0 +1,1149 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARFILE
+ *
+ * Parsing of a Jar file
+ */
+
+#define JAR_SIZE 256
+
+#include "jar.h"
+
+#include "jarint.h"
+#include "jarfile.h"
+
+/* commercial compression */
+#include "jzlib.h"
+
+#ifdef XP_UNIX
+#include "sys/stat.h"
+#endif
+
+
+/* extracting */
+
+static int jar_guess_jar (char *filename, JAR_FILE fp);
+
+static int jar_inflate_memory
+ (unsigned int method, long *length, long expected_out_len, char ZHUGEP **data);
+
+static int jar_physical_extraction
+ (JAR_FILE fp, char *outpath, long offset, long length);
+
+static int jar_physical_inflate
+ (JAR_FILE fp, char *outpath, long offset,
+ long length, unsigned int method);
+
+static int jar_verify_extract
+ (JAR *jar, char *path, char *physical_path);
+
+static JAR_Physical *jar_get_physical (JAR *jar, char *pathname);
+
+static int jar_extract_manifests (JAR *jar, jarArch format, JAR_FILE fp);
+
+static int jar_extract_mf (JAR *jar, jarArch format, JAR_FILE fp, char *ext);
+
+
+/* indexing */
+
+static int jar_gen_index (JAR *jar, jarArch format, JAR_FILE fp);
+
+static int jar_listtar (JAR *jar, JAR_FILE fp);
+
+static int jar_listzip (JAR *jar, JAR_FILE fp);
+
+
+/* conversions */
+
+static int dosdate (char *date, char *s);
+
+static int dostime (char *time, char *s);
+
+static unsigned int xtoint (unsigned char *ii);
+
+static unsigned long xtolong (unsigned char *ll);
+
+static long atoo (char *s);
+
+/*
+ * J A R _ p a s s _ a r c h i v e
+ *
+ * For use by naive clients. Slam an entire archive file
+ * into this function. We extract manifests, parse, index
+ * the archive file, and do whatever nastiness.
+ *
+ */
+
+int JAR_pass_archive
+ (JAR *jar, jarArch format, char *filename, const char *url)
+ {
+ JAR_FILE fp;
+ int status = 0;
+
+ if (filename == NULL)
+ return JAR_ERR_GENERAL;
+
+ if ((fp = JAR_FOPEN (filename, "rb")) != NULL)
+ {
+ if (format == jarArchGuess)
+ format = (jarArch)jar_guess_jar (filename, fp);
+
+ jar->format = format;
+ jar->url = url ? PORT_Strdup (url) : NULL;
+ jar->filename = PORT_Strdup (filename);
+
+ status = jar_gen_index (jar, format, fp);
+
+ if (status == 0)
+ status = jar_extract_manifests (jar, format, fp);
+
+ JAR_FCLOSE (fp);
+
+ if (status < 0)
+ return status;
+
+ /* people were expecting it this way */
+ return jar->valid;
+ }
+ else
+ {
+ /* file not found */
+ return JAR_ERR_FNF;
+ }
+ }
+
+/*
+ * J A R _ p a s s _ a r c h i v e _ u n v e r i f i e d
+ *
+ * Same as JAR_pass_archive, but doesn't parse signatures.
+ *
+ */
+int JAR_pass_archive_unverified
+ (JAR *jar, jarArch format, char *filename, const char *url)
+{
+ JAR_FILE fp;
+ int status = 0;
+
+ if (filename == NULL) {
+ return JAR_ERR_GENERAL;
+ }
+
+ if ((fp = JAR_FOPEN (filename, "rb")) != NULL) {
+ if (format == jarArchGuess) {
+ format = (jarArch)jar_guess_jar (filename, fp);
+ }
+
+ jar->format = format;
+ jar->url = url ? PORT_Strdup (url) : NULL;
+ jar->filename = PORT_Strdup (filename);
+
+ status = jar_gen_index (jar, format, fp);
+
+ if (status == 0) {
+ status = jar_extract_mf(jar, format, fp, "mf");
+ }
+
+ JAR_FCLOSE (fp);
+
+ if (status < 0) {
+ return status;
+ }
+
+ /* people were expecting it this way */
+ return jar->valid;
+ } else {
+ /* file not found */
+ return JAR_ERR_FNF;
+ }
+}
+
+/*
+ * J A R _ v e r i f i e d _ e x t r a c t
+ *
+ * Optimization: keep a file descriptor open
+ * inside the JAR structure, so we don't have to
+ * open the file 25 times to run java.
+ *
+ */
+
+int JAR_verified_extract
+ (JAR *jar, char *path, char *outpath)
+ {
+ int status;
+
+ status = JAR_extract (jar, path, outpath);
+
+ if (status >= 0)
+ return jar_verify_extract (jar, path, outpath);
+ else
+ return status;
+ }
+
+int JAR_extract
+ (JAR *jar, char *path, char *outpath)
+ {
+ int result;
+
+ JAR_FILE fp;
+ JAR_Physical *phy;
+
+ if (jar->fp == NULL && jar->filename)
+ {
+ jar->fp = (FILE*)JAR_FOPEN (jar->filename, "rb");
+ }
+
+ if (jar->fp == NULL)
+ {
+ /* file not found */
+ return JAR_ERR_FNF;
+ }
+
+ phy = jar_get_physical (jar, path);
+
+ if (phy)
+ {
+ if (phy->compression != 0 && phy->compression != 8)
+ {
+ /* unsupported compression method */
+ result = JAR_ERR_CORRUPT;
+ }
+
+ if (phy->compression == 0)
+ {
+ result = jar_physical_extraction
+ ((PRFileDesc*)jar->fp, outpath, phy->offset, phy->length);
+ }
+ else
+ {
+ result = jar_physical_inflate
+ ((PRFileDesc*)jar->fp, outpath, phy->offset, phy->length,
+ (unsigned int) phy->compression);
+ }
+
+#ifdef XP_UNIX
+ if (phy->mode)
+ chmod (outpath, 0400 | (mode_t) phy->mode);
+#endif
+ }
+ else
+ {
+ /* pathname not found in archive */
+ result = JAR_ERR_PNF;
+ }
+
+ return result;
+ }
+
+/*
+ * p h y s i c a l _ e x t r a c t i o n
+ *
+ * This needs to be done in chunks of say 32k, instead of
+ * in one bulk calloc. (Necessary under Win16 platform.)
+ * This is done for uncompressed entries only.
+ *
+ */
+
+#define CHUNK 32768
+
+static int jar_physical_extraction
+ (JAR_FILE fp, char *outpath, long offset, long length)
+ {
+ JAR_FILE out;
+
+ char *buffer;
+ long at, chunk;
+
+ int status = 0;
+
+ buffer = (char *) PORT_ZAlloc (CHUNK);
+
+ if (buffer == NULL)
+ return JAR_ERR_MEMORY;
+
+ if ((out = JAR_FOPEN (outpath, "wb")) != NULL)
+ {
+ at = 0;
+
+ JAR_FSEEK (fp, offset, (PRSeekWhence)0);
+
+ while (at < length)
+ {
+ chunk = (at + CHUNK <= length) ? CHUNK : length - at;
+
+ if (JAR_FREAD (fp, buffer, chunk) != chunk)
+ {
+ status = JAR_ERR_DISK;
+ break;
+ }
+
+ at += chunk;
+
+ if (JAR_FWRITE (out, buffer, chunk) < chunk)
+ {
+ /* most likely a disk full error */
+ status = JAR_ERR_DISK;
+ break;
+ }
+ }
+ JAR_FCLOSE (out);
+ }
+ else
+ {
+ /* error opening output file */
+ status = JAR_ERR_DISK;
+ }
+
+ PORT_Free (buffer);
+ return status;
+ }
+
+/*
+ * j a r _ p h y s i c a l _ i n f l a t e
+ *
+ * Inflate a range of bytes in a file, writing the inflated
+ * result to "outpath". Chunk based.
+ *
+ */
+
+/* input and output chunks differ, assume 4x compression */
+
+#define ICHUNK 8192
+#define OCHUNK 32768
+
+static int jar_physical_inflate
+ (JAR_FILE fp, char *outpath, long offset,
+ long length, unsigned int method)
+ {
+ z_stream zs;
+
+ JAR_FILE out;
+
+ long at, chunk;
+ char *inbuf, *outbuf;
+
+ int status = 0;
+
+ unsigned long prev_total, ochunk, tin;
+
+ if ((inbuf = (char *) PORT_ZAlloc (ICHUNK)) == NULL)
+ return JAR_ERR_MEMORY;
+
+ if ((outbuf = (char *) PORT_ZAlloc (OCHUNK)) == NULL)
+ {
+ PORT_Free (inbuf);
+ return JAR_ERR_MEMORY;
+ }
+
+ PORT_Memset (&zs, 0, sizeof (zs));
+ status = inflateInit2 (&zs, -MAX_WBITS);
+
+ if (status != Z_OK)
+ return JAR_ERR_GENERAL;
+
+ if ((out = JAR_FOPEN (outpath, "wb")) != NULL)
+ {
+ at = 0;
+
+ JAR_FSEEK (fp, offset, (PRSeekWhence)0);
+
+ while (at < length)
+ {
+ chunk = (at + ICHUNK <= length) ? ICHUNK : length - at;
+
+ if (JAR_FREAD (fp, inbuf, chunk) != chunk)
+ {
+ /* incomplete read */
+ return JAR_ERR_CORRUPT;
+ }
+
+ at += chunk;
+
+ zs.next_in = (Bytef *) inbuf;
+ zs.avail_in = chunk;
+ zs.avail_out = OCHUNK;
+
+ tin = zs.total_in;
+
+ while ((zs.total_in - tin < chunk) || (zs.avail_out == 0))
+ {
+ prev_total = zs.total_out;
+
+ zs.next_out = (Bytef *) outbuf;
+ zs.avail_out = OCHUNK;
+
+ status = inflate (&zs, Z_NO_FLUSH);
+
+ if (status != Z_OK && status != Z_STREAM_END)
+ {
+ /* error during decompression */
+ return JAR_ERR_CORRUPT;
+ }
+
+ ochunk = zs.total_out - prev_total;
+
+ if (JAR_FWRITE (out, outbuf, ochunk) < ochunk)
+ {
+ /* most likely a disk full error */
+ status = JAR_ERR_DISK;
+ break;
+ }
+
+ if (status == Z_STREAM_END)
+ break;
+ }
+ }
+
+ JAR_FCLOSE (out);
+ status = inflateEnd (&zs);
+ }
+ else
+ {
+ /* error opening output file */
+ status = JAR_ERR_DISK;
+ }
+
+ PORT_Free (inbuf);
+ PORT_Free (outbuf);
+
+ return status;
+ }
+
+/*
+ * j a r _ i n f l a t e _ m e m o r y
+ *
+ * Call zlib to inflate the given memory chunk. It is re-XP_ALLOC'd,
+ * and thus appears to operate inplace to the caller.
+ *
+ */
+
+static int jar_inflate_memory
+ (unsigned int method, long *length, long expected_out_len, char ZHUGEP **data)
+ {
+ int status;
+ z_stream zs;
+
+ long insz, outsz;
+
+ char *inbuf, *outbuf;
+
+ inbuf = *data;
+ insz = *length;
+
+ outsz = expected_out_len;
+ outbuf = (char*)PORT_ZAlloc (outsz);
+
+ if (outbuf == NULL)
+ return JAR_ERR_MEMORY;
+
+ PORT_Memset (&zs, 0, sizeof (zs));
+
+ status = inflateInit2 (&zs, -MAX_WBITS);
+
+ if (status < 0)
+ {
+ /* error initializing zlib stream */
+ return JAR_ERR_GENERAL;
+ }
+
+ zs.next_in = (Bytef *) inbuf;
+ zs.next_out = (Bytef *) outbuf;
+
+ zs.avail_in = insz;
+ zs.avail_out = outsz;
+
+ status = inflate (&zs, Z_FINISH);
+
+ if (status != Z_OK && status != Z_STREAM_END)
+ {
+ /* error during deflation */
+ return JAR_ERR_GENERAL;
+ }
+
+ status = inflateEnd (&zs);
+
+ if (status != Z_OK)
+ {
+ /* error during deflation */
+ return JAR_ERR_GENERAL;
+ }
+
+ PORT_Free (*data);
+
+ *data = outbuf;
+ *length = zs.total_out;
+
+ return 0;
+ }
+
+/*
+ * v e r i f y _ e x t r a c t
+ *
+ * Validate signature on the freshly extracted file.
+ *
+ */
+
+static int jar_verify_extract (JAR *jar, char *path, char *physical_path)
+ {
+ int status;
+ JAR_Digest dig;
+
+ PORT_Memset (&dig, 0, sizeof (JAR_Digest));
+ status = JAR_digest_file (physical_path, &dig);
+
+ if (!status)
+ status = JAR_verify_digest (jar, path, &dig);
+
+ return status;
+ }
+
+/*
+ * g e t _ p h y s i c a l
+ *
+ * Let's get physical.
+ * Obtains the offset and length of this file in the jar file.
+ *
+ */
+
+static JAR_Physical *jar_get_physical (JAR *jar, char *pathname)
+ {
+ JAR_Item *it;
+
+ JAR_Physical *phy;
+
+ ZZLink *link;
+ ZZList *list;
+
+ list = jar->phy;
+
+ if (ZZ_ListEmpty (list))
+ return NULL;
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ it = link->thing;
+ if (it->type == jarTypePhy
+ && it->pathname && !PORT_Strcmp (it->pathname, pathname))
+ {
+ phy = (JAR_Physical *) it->data;
+ return phy;
+ }
+ }
+
+ return NULL;
+ }
+
+/*
+ * j a r _ e x t r a c t _ m a n i f e s t s
+ *
+ * Extract the manifest files and parse them,
+ * from an open archive file whose contents are known.
+ *
+ */
+
+static int jar_extract_manifests (JAR *jar, jarArch format, JAR_FILE fp)
+ {
+ int status;
+
+ if (format != jarArchZip && format != jarArchTar)
+ return JAR_ERR_CORRUPT;
+
+ if ((status = jar_extract_mf (jar, format, fp, "mf")) < 0)
+ return status;
+
+ if ((status = jar_extract_mf (jar, format, fp, "sf")) < 0)
+ return status;
+
+ if ((status = jar_extract_mf (jar, format, fp, "rsa")) < 0)
+ return status;
+
+ if ((status = jar_extract_mf (jar, format, fp, "dsa")) < 0)
+ return status;
+
+ return 0;
+ }
+
+/*
+ * j a r _ e x t r a c t _ m f
+ *
+ * Extracts manifest files based on an extension, which
+ * should be .MF, .SF, .RSA, etc. Order of the files is now no
+ * longer important when zipping jar files.
+ *
+ */
+
+static int jar_extract_mf (JAR *jar, jarArch format, JAR_FILE fp, char *ext)
+ {
+ JAR_Item *it;
+
+ JAR_Physical *phy;
+
+ ZZLink *link;
+ ZZList *list;
+
+ char *fn, *e;
+ char ZHUGEP *manifest;
+
+ long length;
+ int status, ret = 0, num;
+
+ list = jar->phy;
+
+ if (ZZ_ListEmpty (list))
+ return JAR_ERR_PNF;
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ it = link->thing;
+ if (it->type == jarTypePhy
+ && !PORT_Strncmp (it->pathname, "META-INF", 8))
+ {
+ phy = (JAR_Physical *) it->data;
+
+ if (PORT_Strlen (it->pathname) < 8)
+ continue;
+
+ fn = it->pathname + 8;
+ if (*fn == '/' || *fn == '\\') fn++;
+
+ if (*fn == 0)
+ {
+ /* just a directory entry */
+ continue;
+ }
+
+ /* skip to extension */
+ for (e = fn; *e && *e != '.'; e++)
+ /* yip */ ;
+
+ /* and skip dot */
+ if (*e == '.') e++;
+
+ if (PORT_Strcasecmp (ext, e))
+ {
+ /* not the right extension */
+ continue;
+ }
+
+ if (phy->length == 0)
+ {
+ /* manifest files cannot be zero length! */
+ return JAR_ERR_CORRUPT;
+ }
+
+ /* Read in the manifest and parse it */
+ /* FIX? Does this break on win16 for very very large manifest files? */
+
+#ifdef XP_WIN16
+ PORT_Assert( phy->length+1 < 0xFFFF );
+#endif
+
+ manifest = (char ZHUGEP *) PORT_ZAlloc (phy->length + 1);
+ if (manifest)
+ {
+ JAR_FSEEK (fp, phy->offset, (PRSeekWhence)0);
+ num = JAR_FREAD (fp, manifest, phy->length);
+
+ if (num != phy->length)
+ {
+ /* corrupt archive file */
+ return JAR_ERR_CORRUPT;
+ }
+
+ if (phy->compression == 8)
+ {
+ length = phy->length;
+
+ status = jar_inflate_memory ((unsigned int) phy->compression, &length, phy->uncompressed_length, &manifest);
+
+ if (status < 0)
+ return status;
+ }
+ else if (phy->compression)
+ {
+ /* unsupported compression method */
+ return JAR_ERR_CORRUPT;
+ }
+ else
+ length = phy->length;
+
+ status = JAR_parse_manifest
+ (jar, manifest, length, it->pathname, "url");
+
+ PORT_Free (manifest);
+
+ if (status < 0 && ret == 0) ret = status;
+ }
+ else
+ return JAR_ERR_MEMORY;
+ }
+ else if (it->type == jarTypePhy)
+ {
+ /* ordinary file */
+ }
+ }
+
+ return ret;
+ }
+
+/*
+ * j a r _ g e n _ i n d e x
+ *
+ * Generate an index for the various types of
+ * known archive files. Right now .ZIP and .TAR
+ *
+ */
+
+static int jar_gen_index (JAR *jar, jarArch format, JAR_FILE fp)
+ {
+ int result = JAR_ERR_CORRUPT;
+ JAR_FSEEK (fp, 0, (PRSeekWhence)0);
+
+ switch (format)
+ {
+ case jarArchZip:
+ result = jar_listzip (jar, fp);
+ break;
+
+ case jarArchTar:
+ result = jar_listtar (jar, fp);
+ break;
+ }
+
+ JAR_FSEEK (fp, 0, (PRSeekWhence)0);
+ return result;
+ }
+
+
+/*
+ * j a r _ l i s t z i p
+ *
+ * List the physical contents of a Phil Katz
+ * style .ZIP file into the JAR linked list.
+ *
+ */
+
+static int jar_listzip (JAR *jar, JAR_FILE fp)
+ {
+ int err = 0;
+
+ long pos = 0L;
+ char filename [JAR_SIZE];
+
+ char date [9], time [9];
+ char sig [4];
+
+ unsigned int compression;
+ unsigned int filename_len, extra_len;
+
+ struct ZipLocal *Local;
+ struct ZipCentral *Central;
+ struct ZipEnd *End;
+
+ /* phy things */
+
+ ZZLink *ent;
+ JAR_Item *it;
+ JAR_Physical *phy;
+
+ Local = (struct ZipLocal *) PORT_ZAlloc (30);
+ Central = (struct ZipCentral *) PORT_ZAlloc (46);
+ End = (struct ZipEnd *) PORT_ZAlloc (22);
+
+ if (!Local || !Central || !End)
+ {
+ /* out of memory */
+ err = JAR_ERR_MEMORY;
+ goto loser;
+ }
+
+ while (1)
+ {
+ JAR_FSEEK (fp, pos, (PRSeekWhence)0);
+
+ if (JAR_FREAD (fp, (char *) sig, 4) != 4)
+ {
+ /* zip file ends prematurely */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+ JAR_FSEEK (fp, pos, (PRSeekWhence)0);
+
+ if (xtolong ((unsigned char *)sig) == LSIG)
+ {
+ JAR_FREAD (fp, (char *) Local, 30);
+
+ filename_len = xtoint ((unsigned char *) Local->filename_len);
+ extra_len = xtoint ((unsigned char *) Local->extrafield_len);
+
+ if (filename_len >= JAR_SIZE)
+ {
+ /* corrupt zip file */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+ if (JAR_FREAD (fp, filename, filename_len) != filename_len)
+ {
+ /* truncated archive file */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+ filename [filename_len] = 0;
+
+ /* Add this to our jar chain */
+
+ phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical));
+
+ if (phy == NULL)
+ {
+ err = JAR_ERR_MEMORY;
+ goto loser;
+ }
+
+ /* We will index any file that comes our way, but when it comes
+ to actually extraction, compression must be 0 or 8 */
+
+ compression = xtoint ((unsigned char *) Local->method);
+ phy->compression = compression >= 0 &&
+ compression <= 255 ? compression : 222;
+
+ phy->offset = pos + 30 + filename_len + extra_len;
+ phy->length = xtolong ((unsigned char *) Local->size);
+ phy->uncompressed_length = xtolong((unsigned char *) Local->orglen);
+
+ dosdate (date, Local->date);
+ dostime (time, Local->time);
+
+ it = (JAR_Item*)PORT_ZAlloc (sizeof (JAR_Item));
+ if (it == NULL)
+ {
+ err = JAR_ERR_MEMORY;
+ goto loser;
+ }
+
+ it->pathname = PORT_Strdup (filename);
+
+ it->type = jarTypePhy;
+
+ it->data = (unsigned char *) phy;
+ it->size = sizeof (JAR_Physical);
+
+ ent = ZZ_NewLink (it);
+
+ if (ent == NULL)
+ {
+ err = JAR_ERR_MEMORY;
+ goto loser;
+ }
+
+ ZZ_AppendLink (jar->phy, ent);
+
+ pos = phy->offset + phy->length;
+ }
+ else if (xtolong ( (unsigned char *)sig) == CSIG)
+ {
+ if (JAR_FREAD (fp, (char *) Central, 46) != 46)
+ {
+ /* apparently truncated archive */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+#ifdef XP_UNIX
+ /* with unix we need to locate any bits from
+ the protection mask in the external attributes. */
+ {
+ unsigned int attr;
+
+ /* determined empirically */
+ attr = Central->external_attributes [2];
+
+ if (attr)
+ {
+ /* we have to read the filename, again */
+
+ filename_len = xtoint ((unsigned char *) Central->filename_len);
+
+ if (filename_len >= JAR_SIZE)
+ {
+ /* corrupt in central directory */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+ if (JAR_FREAD (fp, filename, filename_len) != filename_len)
+ {
+ /* truncated in central directory */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+
+ filename [filename_len] = 0;
+
+ /* look up this name again */
+ phy = jar_get_physical (jar, filename);
+
+ if (phy)
+ {
+ /* always allow access by self */
+ phy->mode = 0400 | attr;
+ }
+ }
+ }
+#endif
+
+ pos += 46 + xtoint ( (unsigned char *)Central->filename_len)
+ + xtoint ( (unsigned char *)Central->commentfield_len)
+ + xtoint ( (unsigned char *)Central->extrafield_len);
+ }
+ else if (xtolong ( (unsigned char *)sig) == ESIG)
+ {
+ if (JAR_FREAD (fp, (char *) End, 22) != 22)
+ {
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+ else
+ break;
+ }
+ else
+ {
+ /* garbage in archive */
+ err = JAR_ERR_CORRUPT;
+ goto loser;
+ }
+ }
+
+loser:
+
+ if (Local) PORT_Free (Local);
+ if (Central) PORT_Free (Central);
+ if (End) PORT_Free (End);
+
+ return err;
+ }
+
+/*
+ * j a r _ l i s t t a r
+ *
+ * List the physical contents of a Unix
+ * .tar file into the JAR linked list.
+ *
+ */
+
+static int jar_listtar (JAR *jar, JAR_FILE fp)
+ {
+ long pos = 0L;
+
+ long sz, mode;
+ time_t when;
+ union TarEntry tarball;
+
+ char *s;
+
+ /* phy things */
+
+ ZZLink *ent;
+ JAR_Item *it;
+ JAR_Physical *phy;
+
+ while (1)
+ {
+ JAR_FSEEK (fp, pos, (PRSeekWhence)0);
+
+ if (JAR_FREAD (fp, (char *) &tarball, 512) < 512)
+ break;
+
+ if (!*tarball.val.filename)
+ break;
+
+ when = atoo (tarball.val.time);
+ sz = atoo (tarball.val.size);
+ mode = atoo (tarball.val.mode);
+
+
+ /* Tag the end of filename */
+
+ s = tarball.val.filename;
+ while (*s && *s != ' ') s++;
+ *s = 0;
+
+
+ /* Add to our linked list */
+
+ phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical));
+
+ if (phy == NULL)
+ return JAR_ERR_MEMORY;
+
+ phy->compression = 0;
+ phy->offset = pos + 512;
+ phy->length = sz;
+
+ ADDITEM (jar->phy, jarTypePhy,
+ tarball.val.filename, phy, sizeof (JAR_Physical));
+
+
+ /* Advance to next file entry */
+
+ sz += 511;
+ sz = (sz / 512) * 512;
+
+ pos += sz + 512;
+ }
+
+ return 0;
+ }
+
+/*
+ * d o s d a t e
+ *
+ * Not used right now, but keep it in here because
+ * it will be needed.
+ *
+ */
+
+static int dosdate (char *date, char *s)
+ {
+ int num = xtoint ( (unsigned char *)s);
+
+ PR_snprintf (date, 9, "%02d-%02d-%02d",
+ ((num >> 5) & 0x0F), (num & 0x1F), ((num >> 9) + 80));
+
+ return 0;
+ }
+
+/*
+ * d o s t i m e
+ *
+ * Not used right now, but keep it in here because
+ * it will be needed.
+ *
+ */
+
+static int dostime (char *time, char *s)
+ {
+ int num = xtoint ( (unsigned char *)s);
+
+ PR_snprintf (time, 6, "%02d:%02d",
+ ((num >> 11) & 0x1F), ((num >> 5) & 0x3F));
+
+ return 0;
+ }
+
+/*
+ * x t o i n t
+ *
+ * Converts a two byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static unsigned int xtoint (unsigned char *ii)
+ {
+ return (int) (ii [0]) | ((int) ii [1] << 8);
+ }
+
+/*
+ * x t o l o n g
+ *
+ * Converts a four byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static unsigned long xtolong (unsigned char *ll)
+ {
+ unsigned long ret;
+
+ ret = (
+ (((unsigned long) ll [0]) << 0) |
+ (((unsigned long) ll [1]) << 8) |
+ (((unsigned long) ll [2]) << 16) |
+ (((unsigned long) ll [3]) << 24)
+ );
+
+ return ret;
+ }
+
+/*
+ * a t o o
+ *
+ * Ascii octal to decimal.
+ * Used for integer encoding inside tar files.
+ *
+ */
+
+static long atoo (char *s)
+ {
+ long num = 0L;
+
+ while (*s == ' ') s++;
+
+ while (*s >= '0' && *s <= '7')
+ {
+ num <<= 3;
+ num += *s++ - '0';
+ }
+
+ return num;
+ }
+
+/*
+ * g u e s s _ j a r
+ *
+ * Try to guess what kind of JAR file this is.
+ * Maybe tar, maybe zip. Look in the file for magic
+ * or at its filename.
+ *
+ */
+
+static int jar_guess_jar (char *filename, JAR_FILE fp)
+ {
+ char *ext;
+
+ ext = filename + PORT_Strlen (filename) - 4;
+
+ if (!PORT_Strcmp (ext, ".tar"))
+ return jarArchTar;
+
+ return jarArchZip;
+ }
diff --git a/security/nss/lib/jar/jarfile.h b/security/nss/lib/jar/jarfile.h
new file mode 100644
index 000000000..d28b090fa
--- /dev/null
+++ b/security/nss/lib/jar/jarfile.h
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARFILE.H
+ *
+ * Certain constants and structures for the archive format.
+ *
+ */
+
+/* ZIP */
+
+struct ZipLocal
+ {
+ char signature [4];
+ char word [2];
+ char bitflag [2];
+ char method [2];
+ char time [2];
+ char date [2];
+ char crc32 [4];
+ char size [4];
+ char orglen [4];
+ char filename_len [2];
+ char extrafield_len [2];
+ };
+
+struct ZipCentral
+ {
+ char signature [4];
+ char version_made_by [2];
+ char version [2];
+ char bitflag [2];
+ char method [2];
+ char time [2];
+ char date [2];
+ char crc32 [4];
+ char size [4];
+ char orglen [4];
+ char filename_len [2];
+ char extrafield_len [2];
+ char commentfield_len [2];
+ char diskstart_number [2];
+ char internal_attributes [2];
+ char external_attributes [4];
+ char localhdr_offset [4];
+ };
+
+struct ZipEnd
+ {
+ char signature [4];
+ char disk_nr [2];
+ char start_central_dir [2];
+ char total_entries_disk [2];
+ char total_entries_archive [2];
+ char central_dir_size [4];
+ char offset_central_dir [4];
+ char commentfield_len [2];
+ };
+
+#define LSIG 0x04034B50l
+#define CSIG 0x02014B50l
+#define ESIG 0x06054B50l
+
+/* TAR */
+
+union TarEntry
+ {
+ struct header
+ {
+ char filename [100];
+ char mode [8];
+ char uid [8];
+ char gid [8];
+ char size [12];
+ char time [12];
+ char checksum [8];
+ char linkflag;
+ char linkname [100];
+ }
+ val;
+
+ char buffer [512];
+ };
diff --git a/security/nss/lib/jar/jarint.c b/security/nss/lib/jar/jarint.c
new file mode 100644
index 000000000..4c8da5986
--- /dev/null
+++ b/security/nss/lib/jar/jarint.c
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/*
+ * Internal libjar routines.
+ */
+
+#include "jar.h"
+#include "jarint.h"
+
+/*-----------------------------------------------------------------------
+ * JAR_FOPEN_to_PR_Open
+ * Translate JAR_FOPEN arguments to PR_Open arguments
+ */
+PRFileDesc*
+JAR_FOPEN_to_PR_Open(const char* name, const char *mode)
+{
+
+ PRIntn prflags=0, prmode=0;
+
+ /* Get read/write flags */
+ if(strchr(mode, 'r') && !strchr(mode, '+')) {
+ prflags |= PR_RDONLY;
+ } else if( (strchr(mode, 'w') || strchr(mode, 'a')) &&
+ !strchr(mode,'+') ) {
+ prflags |= PR_WRONLY;
+ } else {
+ prflags |= PR_RDWR;
+ }
+
+ /* Create a new file? */
+ if(strchr(mode, 'w') || strchr(mode, 'a')) {
+ prflags |= PR_CREATE_FILE;
+ }
+
+ /* Append? */
+ if(strchr(mode, 'a')) {
+ prflags |= PR_APPEND;
+ }
+
+ /* Truncate? */
+ if(strchr(mode, 'w')) {
+ prflags |= PR_TRUNCATE;
+ }
+
+ /* We can't do umask because it isn't XP. Choose some default
+ mode for created files */
+ prmode = 0755;
+
+ return PR_Open(name, prflags, prmode);
+}
diff --git a/security/nss/lib/jar/jarint.h b/security/nss/lib/jar/jarint.h
new file mode 100644
index 000000000..7c437103c
--- /dev/null
+++ b/security/nss/lib/jar/jarint.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+/* JAR internal routines */
+
+#include "nspr.h"
+
+/* definitely required */
+#include "certdb.h"
+#include "key.h"
+#include "base64.h"
+
+extern CERTCertDBHandle *JAR_open_database (void);
+
+extern int JAR_close_database (CERTCertDBHandle *certdb);
+
+extern int jar_close_key_database (SECKEYKeyDBHandle *keydb);
+
+extern SECKEYKeyDBHandle *jar_open_key_database (void);
+
+extern JAR_Signer *JAR_new_signer (void);
+
+extern void JAR_destroy_signer (JAR_Signer *signer);
+
+extern JAR_Signer *jar_get_signer (JAR *jar, char *basename);
+
+extern int jar_append (ZZList *list, int type,
+ char *pathname, void *data, size_t size);
+
+/* Translate fopen mode arg to PR_Open flags and mode */
+PRFileDesc*
+JAR_FOPEN_to_PR_Open(const char *name, const char *mode);
+
+
+#define ADDITEM(list,type,pathname,data,size) \
+ { int err; err = jar_append (list, type, pathname, data, size); \
+ if (err < 0) return err; }
+
+/* Here is some ugliness in the event it is necessary to link
+ with NSPR 1.0 libraries, which do not include an FSEEK. It is
+ difficult to fudge an FSEEK into 1.0 so we use stdio. */
+
+/* stdio */
+#if 0
+#define JAR_FILE FILE *
+#define JAR_FOPEN(fn,mode) fopen(fn,mode)
+#define JAR_FCLOSE fclose
+#define JAR_FSEEK fseek
+#define JAR_FREAD(fp,buf,siz) fread(buf,1,siz,fp)
+#define JAR_FWRITE(fp,buf,siz) fwrite(buf,1,siz,fp)
+#endif
+
+#if 0
+/* nspr 1.0 suite */
+#define JAR_FILE PRFileHandle
+#define JAR_FOPEN(fn,mode) PR_OpenFile(fn,0,mode)
+#define JAR_FCLOSE PR_CLOSE
+#define JAR_FSEEK (no-equivalent)
+#define JAR_FREAD PR_READ
+#define JAR_FWRITE PR_WRITE
+#endif
+
+/* nspr 2.0 suite */
+#define JAR_FILE PRFileDesc *
+/* #define JAR_FOPEN(fn,mode) PR_Open(fn,0,0) */
+#define JAR_FOPEN(fn,mode) JAR_FOPEN_to_PR_Open(fn,mode)
+#define JAR_FCLOSE PR_Close
+#define JAR_FSEEK PR_Seek
+#define JAR_FREAD PR_Read
+#define JAR_FWRITE PR_Write
+
+#if 0
+/* nav XP suite, note argument order */
+#define JAR_FILE XP_File
+#define JAR_FOPEN(fn,mode) XP_FileOpen(fn,xpURL,mode)
+#define JAR_FCLOSE XP_FileClose
+#define JAR_FSEEK XP_FileSeek
+#define JAR_FREAD(fp,buf,siz) XP_FileRead(buf,siz,fp)
+#define JAR_FWRITE(fp,buf,siz) XP_FileWrite(buf,siz,fp)
+#endif
+
+int jar_create_pk7
+ (CERTCertDBHandle *certdb, SECKEYKeyDBHandle *keydb,
+ CERTCertificate *cert, char *password, JAR_FILE infp,
+ JAR_FILE outfp);
+
diff --git a/security/nss/lib/jar/jarjart.c b/security/nss/lib/jar/jarjart.c
new file mode 100644
index 000000000..e188da89b
--- /dev/null
+++ b/security/nss/lib/jar/jarjart.c
@@ -0,0 +1,354 @@
+/*
+ * 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. */
+
+/* from certdb.h */
+#define CERTDB_USER (1<<6)
+
+#if 0
+/* from certdb.h */
+typedef SECStatus (* PermCertCallback)(CERTCertificate *cert, SECItem *k, void *pdata);
+/* from certdb.h */
+SECStatus SEC_TraversePermCerts
+ (CERTCertDBHandle *handle, PermCertCallback certfunc, void *udata);
+#endif
+
+/*
+ * 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 && cert->dbEntry)
+ {
+ /* name = cert->dbEntry->nickname; */
+ 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;
+ CERTCertDBHandle *certdb;
+
+ char *ugly_list;
+
+ certdb = JAR_open_database();
+
+ /* a little something */
+ ugly_list = (char*)PORT_ZAlloc (16);
+
+ if (ugly_list)
+ {
+ *ugly_list = 0;
+
+ status = SEC_TraversePermCerts
+ (certdb, jar_list_cert_callback, (void *) &ugly_list);
+ }
+
+ JAR_close_database (certdb);
+
+ return status ? 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;
+ SECKEYKeyDBHandle *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;
+ }
diff --git a/security/nss/lib/jar/jarjart.h b/security/nss/lib/jar/jarjart.h
new file mode 100644
index 000000000..bb4596e90
--- /dev/null
+++ b/security/nss/lib/jar/jarjart.h
@@ -0,0 +1,72 @@
+/*
+ * 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.h
+ *
+ * Functions for the Jartool, which is written in Java and
+ * requires wrappers located elsewhere in the client.
+ *
+ * Do not call these unless you are the Jartool, no matter
+ * how convenient they may appear.
+ *
+ */
+
+#ifndef _JARJART_H_
+#define _JARJART_H_
+
+/* return a list of certificate nicknames, separated by \n's */
+extern char *JAR_JAR_list_certs (void);
+
+/* validate archive, simple api */
+extern int JAR_JAR_validate_archive (char *filename);
+
+/* begin hash */
+extern void *JAR_JAR_new_hash (int alg);
+
+/* hash a streaming pile */
+extern void *JAR_JAR_hash (int alg, void *cookie, int length, void *data);
+
+/* end hash */
+extern void *JAR_JAR_end_hash (int alg, void *cookie);
+
+/* sign the archive (given an .SF file) with the given cert.
+ The password argument is a relic, PKCS11 now handles that. */
+
+extern int JAR_JAR_sign_archive
+ (char *nickname, char *password, char *sf, char *outsig);
+
+/* convert status to text */
+extern char *JAR_JAR_get_error (int status);
+
+#endif
diff --git a/security/nss/lib/jar/jarnav.c b/security/nss/lib/jar/jarnav.c
new file mode 100644
index 000000000..2100948ab
--- /dev/null
+++ b/security/nss/lib/jar/jarnav.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARNAV.C
+ *
+ * JAR stuff needed for client only.
+ *
+ */
+
+#include "jar.h"
+#include "jarint.h"
+
+/* from proto.h */
+#ifdef MOZILLA_CLIENT
+extern MWContext *XP_FindSomeContext(void);
+#endif
+
+/* sigh */
+extern MWContext *FE_GetInitContext(void);
+
+/* To return an MWContext for Java */
+static MWContext *(*jar_fn_FindSomeContext) (void) = NULL;
+
+/* To fabricate an MWContext for FE_GetPassword */
+static MWContext *(*jar_fn_GetInitContext) (void) = NULL;
+
+/*
+ * J A R _ i n i t
+ *
+ * Initialize the JAR functions.
+ *
+ */
+
+void JAR_init (void)
+ {
+#ifdef MOZILLA_CLIENT
+ JAR_init_callbacks (XP_GetString, XP_FindSomeContext, FE_GetInitContext);
+#else
+ JAR_init_callbacks (XP_GetString, NULL, NULL);
+#endif
+ }
+
+/*
+ * J A R _ s e t _ c o n t e x t
+ *
+ * Set the jar window context for use by PKCS11, since
+ * it may be needed to prompt the user for a password.
+ *
+ */
+
+int JAR_set_context (JAR *jar, MWContext *mw)
+ {
+ if (mw)
+ {
+ jar->mw = mw;
+ }
+ else
+ {
+ /* jar->mw = XP_FindSomeContext(); */
+ jar->mw = NULL;
+
+ /*
+ * We can't find a context because we're in startup state and none
+ * exist yet. go get an FE_InitContext that only works at initialization
+ * time.
+ */
+
+ /* Turn on the mac when we get the FE_ function */
+ if (jar->mw == NULL)
+ {
+ jar->mw = jar_fn_GetInitContext();
+ }
+ }
+
+ return 0;
+ }
diff --git a/security/nss/lib/jar/jarsign.c b/security/nss/lib/jar/jarsign.c
new file mode 100644
index 000000000..3518bfa26
--- /dev/null
+++ b/security/nss/lib/jar/jarsign.c
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARSIGN
+ *
+ * Routines used in signing archives.
+ */
+
+#define USE_MOZ_THREAD
+
+#include "jar.h"
+#include "jarint.h"
+
+#ifdef USE_MOZ_THREAD
+#include "jarevil.h"
+#endif
+
+#include "pk11func.h"
+
+/* from libevent.h */
+typedef void (*ETVoidPtrFunc) (void * data);
+
+#ifdef MOZILLA_CLIENT
+
+extern void ET_moz_CallFunction (ETVoidPtrFunc fn, void *data);
+
+/* from proto.h */
+/* extern MWContext *XP_FindSomeContext(void); */
+extern void *XP_FindSomeContext(void);
+
+#endif
+
+/* key database wrapper */
+
+/* static SECKEYKeyDBHandle *jar_open_key_database (void); */
+
+/* CHUNQ is our bite size */
+
+#define CHUNQ 64000
+#define FILECHUNQ 32768
+
+/*
+ * J A R _ c a l c u l a t e _ d i g e s t
+ *
+ * Quick calculation of a digest for
+ * the specified block of memory. Will calculate
+ * for all supported algorithms, now MD5.
+ *
+ * This version supports huge pointers for WIN16.
+ *
+ */
+
+JAR_Digest * PR_CALLBACK JAR_calculate_digest (void ZHUGEP *data, long length)
+ {
+ long chunq;
+ JAR_Digest *dig;
+
+ unsigned int md5_length, sha1_length;
+
+ PK11Context *md5 = 0;
+ PK11Context *sha1 = 0;
+
+ dig = (JAR_Digest *) PORT_ZAlloc (sizeof (JAR_Digest));
+
+ if (dig == NULL)
+ {
+ /* out of memory allocating digest */
+ return NULL;
+ }
+
+#if defined(XP_WIN16)
+ PORT_Assert ( !IsBadHugeReadPtr(data, length) );
+#endif
+
+ md5 = PK11_CreateDigestContext (SEC_OID_MD5);
+ sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
+
+ if (length >= 0)
+ {
+ PK11_DigestBegin (md5);
+ PK11_DigestBegin (sha1);
+
+ do {
+ chunq = length;
+
+#ifdef XP_WIN16
+ if (length > CHUNQ) chunq = CHUNQ;
+
+ /*
+ * If the block of data crosses one or more segment
+ * boundaries then only pass the chunk of data in the
+ * first segment.
+ *
+ * This allows the data to be treated as FAR by the
+ * PK11_DigestOp(...) routine.
+ *
+ */
+
+ if (OFFSETOF(data) + chunq >= 0x10000)
+ chunq = 0x10000 - OFFSETOF(data);
+#endif
+
+ PK11_DigestOp (md5, (unsigned char*)data, chunq);
+ PK11_DigestOp (sha1, (unsigned char*)data, chunq);
+
+ length -= chunq;
+ data = ((char ZHUGEP *) data + chunq);
+ }
+ while (length > 0);
+
+ PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
+ PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
+
+ PK11_DestroyContext (md5, PR_TRUE);
+ PK11_DestroyContext (sha1, PR_TRUE);
+ }
+
+ return dig;
+ }
+
+/*
+ * J A R _ d i g e s t _ f i l e
+ *
+ * Calculates the MD5 and SHA1 digests for a file
+ * present on disk, and returns these in JAR_Digest struct.
+ *
+ */
+
+int JAR_digest_file (char *filename, JAR_Digest *dig)
+ {
+ JAR_FILE fp;
+
+ int num;
+ unsigned char *buf;
+
+ PK11Context *md5 = 0;
+ PK11Context *sha1 = 0;
+
+ unsigned int md5_length, sha1_length;
+
+ buf = (unsigned char *) PORT_ZAlloc (FILECHUNQ);
+ if (buf == NULL)
+ {
+ /* out of memory */
+ return JAR_ERR_MEMORY;
+ }
+
+ if ((fp = JAR_FOPEN (filename, "rb")) == 0)
+ {
+ /* perror (filename); FIX XXX XXX XXX XXX XXX XXX */
+ PORT_Free (buf);
+ return JAR_ERR_FNF;
+ }
+
+ md5 = PK11_CreateDigestContext (SEC_OID_MD5);
+ sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
+
+ if (md5 == NULL || sha1 == NULL)
+ {
+ /* can't generate digest contexts */
+ PORT_Free (buf);
+ JAR_FCLOSE (fp);
+ return JAR_ERR_GENERAL;
+ }
+
+ PK11_DigestBegin (md5);
+ PK11_DigestBegin (sha1);
+
+ while (1)
+ {
+ if ((num = JAR_FREAD (fp, buf, FILECHUNQ)) == 0)
+ break;
+
+ PK11_DigestOp (md5, buf, num);
+ PK11_DigestOp (sha1, buf, num);
+ }
+
+ PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
+ PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
+
+ PK11_DestroyContext (md5, PR_TRUE);
+ PK11_DestroyContext (sha1, PR_TRUE);
+
+ PORT_Free (buf);
+ JAR_FCLOSE (fp);
+
+ return 0;
+ }
+
+/*
+ * J A R _ o p e n _ k e y _ d a t a b a s e
+ *
+ */
+
+SECKEYKeyDBHandle *jar_open_key_database (void)
+ {
+ SECKEYKeyDBHandle *keydb;
+
+ keydb = SECKEY_GetDefaultKeyDB();
+
+ if (keydb == NULL)
+ { /* open by file if this fails, if jartool is to call this */ ; }
+
+ return keydb;
+ }
+
+int jar_close_key_database (SECKEYKeyDBHandle *keydb)
+ {
+ /* We never do close it */
+ return 0;
+ }
+
+
+/*
+ * j a r _ c r e a t e _ p k 7
+ *
+ */
+
+static void jar_pk7_out (void *arg, const char *buf, unsigned long len)
+ {
+ JAR_FWRITE ((JAR_FILE) arg, buf, len);
+ }
+
+int jar_create_pk7
+ (CERTCertDBHandle *certdb, SECKEYKeyDBHandle *keydb,
+ CERTCertificate *cert, char *password, JAR_FILE infp, JAR_FILE outfp)
+ {
+ int nb;
+ unsigned char buffer [4096], digestdata[32];
+ SECHashObject *hashObj;
+ void *hashcx;
+ unsigned int len;
+
+ int status = 0;
+ char *errstring;
+
+ SECItem digest;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ void /*MWContext*/ *mw;
+
+ if (outfp == NULL || infp == NULL || cert == NULL)
+ return JAR_ERR_GENERAL;
+
+ /* we sign with SHA */
+ hashObj = &SECHashObjects [HASH_AlgSHA1];
+
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return JAR_ERR_GENERAL;
+
+ (* hashObj->begin)(hashcx);
+
+ while (1)
+ {
+ /* nspr2.0 doesn't support feof
+ if (feof (infp)) break; */
+
+ nb = JAR_FREAD (infp, buffer, sizeof (buffer));
+ if (nb == 0)
+ {
+#if 0
+ if (ferror(infp))
+ {
+ /* PORT_SetError(SEC_ERROR_IO); */ /* FIX */
+ (* hashObj->destroy) (hashcx, PR_TRUE);
+ return JAR_ERR_GENERAL;
+ }
+#endif
+ /* eof */
+ break;
+ }
+ (* hashObj->update) (hashcx, buffer, nb);
+ }
+
+ (* hashObj->end) (hashcx, digestdata, &len, 32);
+ (* hashObj->destroy) (hashcx, PR_TRUE);
+
+ digest.data = digestdata;
+ digest.len = len;
+
+ /* signtool must use any old context it can find since it's
+ calling from inside javaland. */
+
+#ifdef MOZILLA_CLIENT
+ mw = XP_FindSomeContext();
+#else
+ mw = NULL;
+#endif
+
+ PORT_SetError (0);
+
+ cinfo = SEC_PKCS7CreateSignedData
+ (cert, certUsageObjectSigner, NULL,
+ SEC_OID_SHA1, &digest, NULL, (void *) mw);
+
+ if (cinfo == NULL)
+ return JAR_ERR_PK7;
+
+ rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
+ if (rv != SECSuccess)
+ {
+ status = PORT_GetError();
+ SEC_PKCS7DestroyContentInfo (cinfo);
+ return status;
+ }
+
+ /* Having this here forces signtool to always include
+ signing time. */
+
+ rv = SEC_PKCS7AddSigningTime (cinfo);
+ if (rv != SECSuccess)
+ {
+ /* don't check error */
+ }
+
+ PORT_SetError (0);
+
+#ifdef USE_MOZ_THREAD
+ /* if calling from mozilla */
+ rv = jar_moz_encode
+ (cinfo, jar_pk7_out, outfp,
+ NULL, /* pwfn */ NULL, /* pwarg */ (void *) mw);
+#else
+ /* if calling from mozilla thread*/
+ rv = SEC_PKCS7Encode
+ (cinfo, jar_pk7_out, outfp,
+ NULL, /* pwfn */ NULL, /* pwarg */ (void *) mw):
+#endif
+
+ if (rv != SECSuccess)
+ status = PORT_GetError();
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ if (rv != SECSuccess)
+ {
+ errstring = JAR_get_error (status);
+ /*XP_TRACE (("Jar signing failed (reason %d = %s)", status, errstring));*/
+ return status < 0 ? status : JAR_ERR_GENERAL;
+ }
+
+ return 0;
+ }
diff --git a/security/nss/lib/jar/jarver.c b/security/nss/lib/jar/jarver.c
new file mode 100644
index 000000000..2f4f589fe
--- /dev/null
+++ b/security/nss/lib/jar/jarver.c
@@ -0,0 +1,2029 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARVER
+ *
+ * Jarnature Parsing & Verification
+ */
+
+#define USE_MOZ_THREAD
+
+#include "jar.h"
+#include "jarint.h"
+
+#ifdef USE_MOZ_THREAD
+#include "jarevil.h"
+#endif
+#include "cdbhdl.h"
+
+/* to use huge pointers in win16 */
+
+#if !defined(XP_WIN16)
+#define xp_HUGE_MEMCPY PORT_Memcpy
+#define xp_HUGE_STRCPY PORT_Strcpy
+#define xp_HUGE_STRLEN PORT_Strlen
+#define xp_HUGE_STRNCASECMP PORT_Strncasecmp
+#else
+#define xp_HUGE_MEMCPY hmemcpy
+int xp_HUGE_STRNCASECMP (char ZHUGEP *buf, char *key, int len);
+size_t xp_HUGE_STRLEN (char ZHUGEP *s);
+char *xp_HUGE_STRCPY (char *to, char ZHUGEP *from);
+#endif
+
+/* from certdb.h */
+#define CERTDB_USER (1<<6)
+
+#if 0
+/* from certdb.h */
+extern PRBool SEC_CertNicknameConflict
+ (char *nickname, CERTCertDBHandle *handle);
+/* from certdb.h */
+extern SECStatus SEC_AddTempNickname
+ (CERTCertDBHandle *handle, char *nickname, SECItem *certKey);
+/* from certdb.h */
+typedef SECStatus (* PermCertCallback)(CERTCertificate *cert, SECItem *k, void *pdata);
+#endif
+
+/* from certdb.h */
+SECStatus SEC_TraversePermCerts
+ (CERTCertDBHandle *handle, PermCertCallback certfunc, void *udata);
+
+
+#define SZ 512
+
+static int jar_validate_pkcs7
+ (JAR *jar, JAR_Signer *signer, char *data, long length);
+
+static int jar_decode (JAR *jar, char *data, long length);
+
+static void jar_catch_bytes
+ (void *arg, const char *buf, unsigned long len);
+
+static int jar_gather_signers
+ (JAR *jar, JAR_Signer *signer, SEC_PKCS7ContentInfo *cinfo);
+
+static char ZHUGEP *jar_eat_line
+ (int lines, int eating, char ZHUGEP *data, long *len);
+
+static JAR_Digest *jar_digest_section
+ (char ZHUGEP *manifest, long length);
+
+static JAR_Digest *jar_get_mf_digest (JAR *jar, char *path);
+
+static int jar_parse_digital_signature
+ (char *raw_manifest, JAR_Signer *signer, long length, JAR *jar);
+
+static int jar_add_cert
+ (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert);
+
+static CERTCertificate *jar_get_certificate
+ (JAR *jar, long keylen, void *key, int *result);
+
+static char *jar_cert_element (char *name, char *tag, int occ);
+
+static char *jar_choose_nickname (CERTCertificate *cert);
+
+static char *jar_basename (const char *path);
+
+static int jar_signal
+ (int status, JAR *jar, const char *metafile, char *pathname);
+
+static int jar_insanity_check (char ZHUGEP *data, long length);
+
+int jar_parse_mf
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url);
+
+int jar_parse_sf
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url);
+
+int jar_parse_sig
+ (JAR *jar, const char *path, char ZHUGEP *raw_manifest, long length);
+
+int jar_parse_any
+ (JAR *jar, int type, JAR_Signer *signer, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url);
+
+static int jar_internal_digest
+ (JAR *jar, const char *path, char *x_name, JAR_Digest *dig);
+
+/*
+ * J A R _ p a r s e _ m a n i f e s t
+ *
+ * Pass manifest files to this function. They are
+ * decoded and placed into internal representations.
+ *
+ * Accepts both signature and manifest files. Use
+ * the same "jar" for both.
+ *
+ */
+
+int JAR_parse_manifest
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url)
+ {
+
+#if defined(XP_WIN16)
+ PORT_Assert( !IsBadHugeReadPtr(raw_manifest, length) );
+#endif
+
+ /* fill in the path, if supplied. This is a the location
+ of the jar file on disk, if known */
+
+ if (jar->filename == NULL && path)
+ {
+ jar->filename = PORT_Strdup (path);
+ if (jar->filename == NULL)
+ return JAR_ERR_MEMORY;
+ }
+
+ /* fill in the URL, if supplied. This is the place
+ from which the jar file was retrieved. */
+
+ if (jar->url == NULL && url)
+ {
+ jar->url = PORT_Strdup (url);
+ if (jar->url == NULL)
+ return JAR_ERR_MEMORY;
+ }
+
+ /* Determine what kind of file this is from the META-INF
+ directory. It could be MF, SF, or a binary RSA/DSA file */
+
+ if (!xp_HUGE_STRNCASECMP (raw_manifest, "Manifest-Version:", 17))
+ {
+ return jar_parse_mf (jar, raw_manifest, length, path, url);
+ }
+ else if (!xp_HUGE_STRNCASECMP (raw_manifest, "Signature-Version:", 18))
+ {
+ return jar_parse_sf (jar, raw_manifest, length, path, url);
+ }
+ else
+ {
+ /* This is probably a binary signature */
+ return jar_parse_sig (jar, path, raw_manifest, length);
+ }
+ }
+
+/*
+ * j a r _ p a r s e _ s i g
+ *
+ * Pass some manner of RSA or DSA digital signature
+ * on, after checking to see if it comes at an appropriate state.
+ *
+ */
+
+int jar_parse_sig
+ (JAR *jar, const char *path, char ZHUGEP *raw_manifest, long length)
+ {
+ JAR_Signer *signer;
+ int status = JAR_ERR_ORDER;
+
+ if (length <= 128)
+ {
+ /* signature is way too small */
+ return JAR_ERR_SIG;
+ }
+
+ /* make sure that MF and SF have already been processed */
+
+ if (jar->globalmeta == NULL)
+ return JAR_ERR_ORDER;
+
+#if 0
+ /* XXX Turn this on to disable multiple signers */
+ if (jar->digest == NULL)
+ return JAR_ERR_ORDER;
+#endif
+
+ /* Determine whether or not this RSA file has
+ has an associated SF file */
+
+ if (path)
+ {
+ char *owner;
+ owner = jar_basename (path);
+
+ if (owner == NULL)
+ return JAR_ERR_MEMORY;
+
+ signer = jar_get_signer (jar, owner);
+
+ PORT_Free (owner);
+ }
+ else
+ signer = jar_get_signer (jar, "*");
+
+ if (signer == NULL)
+ return JAR_ERR_ORDER;
+
+
+ /* Do not pass a huge pointer to this function,
+ since the underlying security code is unaware. We will
+ never pass >64k through here. */
+
+ if (length > 64000)
+ {
+ /* this digital signature is way too big */
+ return JAR_ERR_SIG;
+ }
+
+#ifdef XP_WIN16
+ /*
+ * For Win16, copy the portion of the raw_buffer containing the digital
+ * signature into another buffer... This insures that the data will
+ * NOT cross a segment boundary. Therefore,
+ * jar_parse_digital_signature(...) does NOT need to deal with HUGE
+ * pointers...
+ */
+
+ {
+ unsigned char *manifest_copy;
+
+ manifest_copy = (unsigned char *) PORT_ZAlloc (length);
+ if (manifest_copy)
+ {
+ xp_HUGE_MEMCPY (manifest_copy, raw_manifest, length);
+
+ status = jar_parse_digital_signature
+ (manifest_copy, signer, length, jar);
+
+ PORT_Free (manifest_copy);
+ }
+ else
+ {
+ /* out of memory */
+ return JAR_ERR_MEMORY;
+ }
+ }
+#else
+ /* don't expense unneeded calloc overhead on non-win16 */
+ status = jar_parse_digital_signature
+ (raw_manifest, signer, length, jar);
+#endif
+
+ return status;
+ }
+
+/*
+ * j a r _ p a r s e _ m f
+ *
+ * Parse the META-INF/manifest.mf file, whose
+ * information applies to all signers.
+ *
+ */
+
+int jar_parse_mf
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url)
+ {
+ if (jar->globalmeta)
+ {
+ /* refuse a second manifest file, if passed for some reason */
+ return JAR_ERR_ORDER;
+ }
+
+
+ /* remember a digest for the global section */
+
+ jar->globalmeta = jar_digest_section (raw_manifest, length);
+
+ if (jar->globalmeta == NULL)
+ return JAR_ERR_MEMORY;
+
+
+ return jar_parse_any
+ (jar, jarTypeMF, NULL, raw_manifest, length, path, url);
+ }
+
+/*
+ * j a r _ p a r s e _ s f
+ *
+ * Parse META-INF/xxx.sf, a digitally signed file
+ * pointing to a subset of MF sections.
+ *
+ */
+
+int jar_parse_sf
+ (JAR *jar, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url)
+ {
+ JAR_Signer *signer = NULL;
+ int status = JAR_ERR_MEMORY;
+
+ if (jar->globalmeta == NULL)
+ {
+ /* It is a requirement that the MF file be passed before the SF file */
+ return JAR_ERR_ORDER;
+ }
+
+ signer = JAR_new_signer();
+
+ if (signer == NULL)
+ goto loser;
+
+ if (path)
+ {
+ signer->owner = jar_basename (path);
+ if (signer->owner == NULL)
+ goto loser;
+ }
+
+
+ /* check for priors. When someone doctors a jar file
+ to contain identical path entries, prevent the second
+ one from affecting JAR functions */
+
+ if (jar_get_signer (jar, signer->owner))
+ {
+ /* someone is trying to spoof us */
+ status = JAR_ERR_ORDER;
+ goto loser;
+ }
+
+
+ /* remember its digest */
+
+ signer->digest = JAR_calculate_digest (raw_manifest, length);
+
+ if (signer->digest == NULL)
+ goto loser;
+
+ /* Add this signer to the jar */
+
+ ADDITEM (jar->signers, jarTypeOwner,
+ signer->owner, signer, sizeof (JAR_Signer));
+
+
+ return jar_parse_any
+ (jar, jarTypeSF, signer, raw_manifest, length, path, url);
+
+loser:
+
+ if (signer)
+ JAR_destroy_signer (signer);
+
+ return status;
+ }
+
+/*
+ * j a r _ p a r s e _ a n y
+ *
+ * Parse a MF or SF manifest file.
+ *
+ */
+
+int jar_parse_any
+ (JAR *jar, int type, JAR_Signer *signer, char ZHUGEP *raw_manifest,
+ long length, const char *path, const char *url)
+ {
+ int status;
+
+ long raw_len;
+
+ JAR_Digest *dig, *mfdig = NULL;
+
+ char line [SZ];
+ char x_name [SZ], x_md5 [SZ], x_sha [SZ];
+
+ char *x_info;
+
+ char *sf_md5 = NULL, *sf_sha1 = NULL;
+
+ *x_name = 0;
+ *x_md5 = 0;
+ *x_sha = 0;
+
+ PORT_Assert( length > 0 );
+ raw_len = length;
+
+#ifdef DEBUG
+ if ((status = jar_insanity_check (raw_manifest, raw_len)) < 0)
+ return status;
+#endif
+
+
+ /* null terminate the first line */
+ raw_manifest = jar_eat_line (0, PR_TRUE, raw_manifest, &raw_len);
+
+
+ /* skip over the preliminary section */
+ /* This is one section at the top of the file with global metainfo */
+
+ while (raw_len)
+ {
+ JAR_Metainfo *met;
+
+ raw_manifest = jar_eat_line (1, PR_TRUE, raw_manifest, &raw_len);
+ if (!*raw_manifest) break;
+
+ met = (JAR_Metainfo*)PORT_ZAlloc (sizeof (JAR_Metainfo));
+ if (met == NULL)
+ return JAR_ERR_MEMORY;
+
+ /* Parse out the header & info */
+
+ if (xp_HUGE_STRLEN (raw_manifest) >= SZ)
+ {
+ /* almost certainly nonsense */
+ continue;
+ }
+
+ xp_HUGE_STRCPY (line, raw_manifest);
+ x_info = line;
+
+ while (*x_info && *x_info != ' ' && *x_info != '\t' && *x_info != ':')
+ x_info++;
+
+ if (*x_info) *x_info++ = 0;
+
+ while (*x_info == ' ' || *x_info == '\t')
+ x_info++;
+
+ /* metainfo (name, value) pair is now (line, x_info) */
+
+ met->header = PORT_Strdup (line);
+ met->info = PORT_Strdup (x_info);
+
+ if (type == jarTypeMF)
+ {
+ ADDITEM (jar->metainfo, jarTypeMeta,
+ /* pathname */ NULL, met, sizeof (JAR_Metainfo));
+ }
+
+ /* For SF files, this metadata may be the digests
+ of the MF file, still in the "met" structure. */
+
+ if (type == jarTypeSF)
+ {
+ if (!PORT_Strcasecmp (line, "MD5-Digest"))
+ sf_md5 = (char *) met->info;
+
+ if (!PORT_Strcasecmp (line, "SHA1-Digest") || !PORT_Strcasecmp (line, "SHA-Digest"))
+ sf_sha1 = (char *) met->info;
+ }
+ }
+
+ if (type == jarTypeSF && jar->globalmeta)
+ {
+ /* this is a SF file which may contain a digest of the manifest.mf's
+ global metainfo. */
+
+ int match = 0;
+ JAR_Digest *glob = jar->globalmeta;
+
+ if (sf_md5)
+ {
+ unsigned int md5_length;
+ unsigned char *md5_digest;
+
+ md5_digest = ATOB_AsciiToData (sf_md5, &md5_length);
+ PORT_Assert( md5_length == MD5_LENGTH );
+
+ if (md5_length != MD5_LENGTH)
+ return JAR_ERR_CORRUPT;
+
+ match = PORT_Memcmp (md5_digest, glob->md5, MD5_LENGTH);
+ }
+
+ if (sf_sha1 && match == 0)
+ {
+ unsigned int sha1_length;
+ unsigned char *sha1_digest;
+
+ sha1_digest = ATOB_AsciiToData (sf_sha1, &sha1_length);
+ PORT_Assert( sha1_length == SHA1_LENGTH );
+
+ if (sha1_length != SHA1_LENGTH)
+ return JAR_ERR_CORRUPT;
+
+ match = PORT_Memcmp (sha1_digest, glob->sha1, SHA1_LENGTH);
+ }
+
+ if (match != 0)
+ {
+ /* global digest doesn't match, SF file therefore invalid */
+ jar->valid = JAR_ERR_METADATA;
+ return JAR_ERR_METADATA;
+ }
+ }
+
+ /* done with top section of global data */
+
+
+ while (raw_len)
+ {
+ *x_md5 = 0;
+ *x_sha = 0;
+ *x_name = 0;
+
+
+ /* If this is a manifest file, attempt to get a digest of the following section,
+ without damaging it. This digest will be saved later. */
+
+ if (type == jarTypeMF)
+ {
+ char ZHUGEP *sec;
+ long sec_len = raw_len;
+
+ if (!*raw_manifest || *raw_manifest == '\n')
+ {
+ /* skip the blank line */
+ sec = jar_eat_line (1, PR_FALSE, raw_manifest, &sec_len);
+ }
+ else
+ sec = raw_manifest;
+
+ if (!xp_HUGE_STRNCASECMP (sec, "Name:", 5))
+ {
+ if (type == jarTypeMF)
+ mfdig = jar_digest_section (sec, sec_len);
+ else
+ mfdig = NULL;
+ }
+ }
+
+
+ while (raw_len)
+ {
+ raw_manifest = jar_eat_line (1, PR_TRUE, raw_manifest, &raw_len);
+ if (!*raw_manifest) break; /* blank line, done with this entry */
+
+ if (xp_HUGE_STRLEN (raw_manifest) >= SZ)
+ {
+ /* almost certainly nonsense */
+ continue;
+ }
+
+
+ /* Parse out the name/value pair */
+
+ xp_HUGE_STRCPY (line, raw_manifest);
+ x_info = line;
+
+ while (*x_info && *x_info != ' ' && *x_info != '\t' && *x_info != ':')
+ x_info++;
+
+ if (*x_info) *x_info++ = 0;
+
+ while (*x_info == ' ' || *x_info == '\t')
+ x_info++;
+
+
+ if (!PORT_Strcasecmp (line, "Name"))
+ PORT_Strcpy (x_name, x_info);
+
+ else if (!PORT_Strcasecmp (line, "MD5-Digest"))
+ PORT_Strcpy (x_md5, x_info);
+
+ else if (!PORT_Strcasecmp (line, "SHA1-Digest")
+ || !PORT_Strcasecmp (line, "SHA-Digest"))
+ {
+ PORT_Strcpy (x_sha, x_info);
+ }
+
+ /* Algorithm list is meta info we don't care about; keeping it out
+ of metadata saves significant space for large jar files */
+
+ else if (!PORT_Strcasecmp (line, "Digest-Algorithms")
+ || !PORT_Strcasecmp (line, "Hash-Algorithms"))
+ {
+ continue;
+ }
+
+ /* Meta info is only collected for the manifest.mf file,
+ since the JAR_get_metainfo call does not support identity */
+
+ else if (type == jarTypeMF)
+ {
+ JAR_Metainfo *met;
+
+ /* this is meta-data */
+
+ met = (JAR_Metainfo*)PORT_ZAlloc (sizeof (JAR_Metainfo));
+
+ if (met == NULL)
+ return JAR_ERR_MEMORY;
+
+ /* metainfo (name, value) pair is now (line, x_info) */
+
+ if ((met->header = PORT_Strdup (line)) == NULL)
+ return JAR_ERR_MEMORY;
+
+ if ((met->info = PORT_Strdup (x_info)) == NULL)
+ return JAR_ERR_MEMORY;
+
+ ADDITEM (jar->metainfo, jarTypeMeta,
+ x_name, met, sizeof (JAR_Metainfo));
+ }
+ }
+
+ if(!x_name || !*x_name) {
+ /* Whatever that was, it wasn't an entry, because we didn't get a name.
+ * We don't really have anything, so don't record this. */
+ continue;
+ }
+
+ dig = (JAR_Digest*)PORT_ZAlloc (sizeof (JAR_Digest));
+ if (dig == NULL)
+ return JAR_ERR_MEMORY;
+
+ if (*x_md5 )
+ {
+ unsigned int binary_length;
+ unsigned char *binary_digest;
+
+ binary_digest = ATOB_AsciiToData (x_md5, &binary_length);
+ PORT_Assert( binary_length == MD5_LENGTH );
+
+ if (binary_length != MD5_LENGTH)
+ return JAR_ERR_CORRUPT;
+
+ memcpy (dig->md5, binary_digest, MD5_LENGTH);
+ dig->md5_status = jarHashPresent;
+ }
+
+ if (*x_sha )
+ {
+ unsigned int binary_length;
+ unsigned char *binary_digest;
+
+ binary_digest = ATOB_AsciiToData (x_sha, &binary_length);
+ PORT_Assert( binary_length == SHA1_LENGTH );
+
+ if (binary_length != SHA1_LENGTH)
+ return JAR_ERR_CORRUPT;
+
+ memcpy (dig->sha1, binary_digest, SHA1_LENGTH);
+ dig->sha1_status = jarHashPresent;
+ }
+
+ PORT_Assert( type == jarTypeMF || type == jarTypeSF );
+
+
+ if (type == jarTypeMF)
+ {
+ ADDITEM (jar->hashes, jarTypeMF, x_name, dig, sizeof (JAR_Digest));
+ }
+ else if (type == jarTypeSF)
+ {
+ ADDITEM (signer->sf, jarTypeSF, x_name, dig, sizeof (JAR_Digest));
+ }
+ else
+ return JAR_ERR_ORDER;
+
+ /* we're placing these calculated digests of manifest.mf
+ sections in a list where they can subsequently be forgotten */
+
+ if (type == jarTypeMF && mfdig)
+ {
+ ADDITEM (jar->manifest, jarTypeSect,
+ x_name, mfdig, sizeof (JAR_Digest));
+
+ mfdig = NULL;
+ }
+
+
+ /* Retrieve our saved SHA1 digest from saved copy and check digests.
+ This is just comparing the digest of the MF section as indicated in
+ the SF file with the one we remembered from parsing the MF file */
+
+ if (type == jarTypeSF)
+ {
+ if ((status = jar_internal_digest (jar, path, x_name, dig)) < 0)
+ return status;
+ }
+ }
+
+ return 0;
+ }
+
+static int jar_internal_digest
+ (JAR *jar, const char *path, char *x_name, JAR_Digest *dig)
+ {
+ int cv;
+ int status;
+
+ JAR_Digest *savdig;
+
+ savdig = jar_get_mf_digest (jar, x_name);
+
+ if (savdig == NULL)
+ {
+ /* no .mf digest for this pathname */
+ status = jar_signal (JAR_ERR_ENTRY, jar, path, x_name);
+ if (status < 0)
+ return 0; /* was continue; */
+ else
+ return status;
+ }
+
+ /* check for md5 consistency */
+ if (dig->md5_status)
+ {
+ cv = PORT_Memcmp (savdig->md5, dig->md5, MD5_LENGTH);
+ /* md5 hash of .mf file is not what expected */
+ if (cv)
+ {
+ status = jar_signal (JAR_ERR_HASH, jar, path, x_name);
+
+ /* bad hash, man */
+
+ dig->md5_status = jarHashBad;
+ savdig->md5_status = jarHashBad;
+
+ if (status < 0)
+ return 0; /* was continue; */
+ else
+ return status;
+ }
+ }
+
+ /* check for sha1 consistency */
+ if (dig->sha1_status)
+ {
+ cv = PORT_Memcmp (savdig->sha1, dig->sha1, SHA1_LENGTH);
+ /* sha1 hash of .mf file is not what expected */
+ if (cv)
+ {
+ status = jar_signal (JAR_ERR_HASH, jar, path, x_name);
+
+ /* bad hash, man */
+
+ dig->sha1_status = jarHashBad;
+ savdig->sha1_status = jarHashBad;
+
+ if (status < 0)
+ return 0; /* was continue; */
+ else
+ return status;
+ }
+ }
+ return 0;
+ }
+
+#ifdef DEBUG
+/*
+ * j a r _ i n s a n i t y _ c h e c k
+ *
+ * Check for illegal characters (or possibly so)
+ * in the manifest files, to detect potential memory
+ * corruption by our neighbors. Debug only, since
+ * not I18N safe.
+ *
+ */
+
+static int jar_insanity_check (char ZHUGEP *data, long length)
+ {
+ int c;
+ long off;
+
+ for (off = 0; off < length; off++)
+ {
+ c = data [off];
+
+ if (c == '\n' || c == '\r' || (c >= ' ' && c <= 128))
+ continue;
+
+ return JAR_ERR_CORRUPT;
+ }
+
+ return 0;
+ }
+#endif
+
+/*
+ * j a r _ p a r s e _ d i g i t a l _ s i g n a t u r e
+ *
+ * Parse an RSA or DSA (or perhaps other) digital signature.
+ * Right now everything is PKCS7.
+ *
+ */
+
+static int jar_parse_digital_signature
+ (char *raw_manifest, JAR_Signer *signer, long length, JAR *jar)
+ {
+#if defined(XP_WIN16)
+ PORT_Assert( LOWORD(raw_manifest) + length < 0xFFFF );
+#endif
+ return jar_validate_pkcs7 (jar, signer, raw_manifest, length);
+ }
+
+/*
+ * j a r _ a d d _ c e r t
+ *
+ * Add information for the given certificate
+ * (or whatever) to the JAR linked list. A pointer
+ * is passed for some relevant reference, say
+ * for example the original certificate.
+ *
+ */
+
+static int jar_add_cert
+ (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert)
+ {
+ JAR_Cert *fing;
+
+ if (cert == NULL)
+ return JAR_ERR_ORDER;
+
+ fing = (JAR_Cert*)PORT_ZAlloc (sizeof (JAR_Cert));
+
+ if (fing == NULL)
+ goto loser;
+
+#ifdef USE_MOZ_THREAD
+ fing->cert = jar_moz_dup (cert);
+#else
+ fing->cert = CERT_DupCertificate (cert);
+#endif
+
+ /* get the certkey */
+
+ fing->length = cert->certKey.len;
+
+ fing->key = (char *) PORT_ZAlloc (fing->length);
+
+ if (fing->key == NULL)
+ goto loser;
+
+ PORT_Memcpy (fing->key, cert->certKey.data, fing->length);
+
+ ADDITEM (signer->certs, type,
+ /* pathname */ NULL, fing, sizeof (JAR_Cert));
+
+ return 0;
+
+loser:
+
+ if (fing)
+ {
+ if (fing->cert)
+ CERT_DestroyCertificate (fing->cert);
+
+ PORT_Free (fing);
+ }
+
+ return JAR_ERR_MEMORY;
+ }
+
+/*
+ * e a t _ l i n e
+ *
+ * Consume an ascii line from the top of a file kept
+ * in memory. This destroys the file in place. This function
+ * handles PC, Mac, and Unix style text files.
+ *
+ */
+
+static char ZHUGEP *jar_eat_line
+ (int lines, int eating, char ZHUGEP *data, long *len)
+ {
+ char ZHUGEP *ret;
+
+ ret = data;
+ if (!*len) return ret;
+
+ /* Eat the requisite number of lines, if any;
+ prior to terminating the current line with a 0. */
+
+ for (/* yip */ ; lines; lines--)
+ {
+ while (*data && *data != '\n')
+ data++;
+
+ /* After the CR, ok to eat one LF */
+
+ if (*data == '\n')
+ data++;
+
+ /* If there are zeros, we put them there */
+
+ while (*data == 0 && data - ret < *len)
+ data++;
+ }
+
+ *len -= data - ret;
+ ret = data;
+
+ if (eating)
+ {
+ /* Terminate this line with a 0 */
+
+ while (*data && *data != '\n' && *data != '\r')
+ data++;
+
+ /* In any case we are allowed to eat CR */
+
+ if (*data == '\r')
+ *data++ = 0;
+
+ /* After the CR, ok to eat one LF */
+
+ if (*data == '\n')
+ *data++ = 0;
+ }
+
+ return ret;
+ }
+
+/*
+ * j a r _ d i g e s t _ s e c t i o n
+ *
+ * Return the digests of the next section of the manifest file.
+ * Does not damage the manifest file, unlike parse_manifest.
+ *
+ */
+
+static JAR_Digest *jar_digest_section
+ (char ZHUGEP *manifest, long length)
+ {
+ long global_len;
+ char ZHUGEP *global_end;
+
+ global_end = manifest;
+ global_len = length;
+
+ while (global_len)
+ {
+ global_end = jar_eat_line (1, PR_FALSE, global_end, &global_len);
+ if (*global_end == 0 || *global_end == '\n')
+ break;
+ }
+
+ return JAR_calculate_digest (manifest, global_end - manifest);
+ }
+
+/*
+ * J A R _ v e r i f y _ d i g e s t
+ *
+ * Verifies that a precalculated digest matches the
+ * expected value in the manifest.
+ *
+ */
+
+int PR_CALLBACK JAR_verify_digest
+ (JAR *jar, const char *name, JAR_Digest *dig)
+ {
+ JAR_Item *it;
+
+ JAR_Digest *shindig;
+
+ ZZLink *link;
+ ZZList *list;
+
+ int result1, result2;
+
+ list = jar->hashes;
+
+ result1 = result2 = 0;
+
+ if (jar->valid < 0)
+ {
+ /* signature not valid */
+ return JAR_ERR_SIG;
+ }
+
+ if (ZZ_ListEmpty (list))
+ {
+ /* empty list */
+ return JAR_ERR_PNF;
+ }
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ it = link->thing;
+ if (it->type == jarTypeMF
+ && it->pathname && !PORT_Strcmp (it->pathname, name))
+ {
+ shindig = (JAR_Digest *) it->data;
+
+ if (shindig->md5_status)
+ {
+ if (shindig->md5_status == jarHashBad)
+ return JAR_ERR_HASH;
+ else
+ result1 = memcmp (dig->md5, shindig->md5, MD5_LENGTH);
+ }
+
+ if (shindig->sha1_status)
+ {
+ if (shindig->sha1_status == jarHashBad)
+ return JAR_ERR_HASH;
+ else
+ result2 = memcmp (dig->sha1, shindig->sha1, SHA1_LENGTH);
+ }
+
+ return (result1 == 0 && result2 == 0) ? 0 : JAR_ERR_HASH;
+ }
+ }
+
+ return JAR_ERR_PNF;
+ }
+
+/*
+ * J A R _ c e r t _ a t t r i b u t e
+ *
+ * Return the named certificate attribute from the
+ * certificate specified by the given key.
+ *
+ */
+
+int PR_CALLBACK JAR_cert_attribute
+ (JAR *jar, jarCert attrib, long keylen, void *key,
+ void **result, unsigned long *length)
+ {
+ int status = 0;
+ char *ret = NULL;
+
+ CERTCertificate *cert;
+
+ CERTCertDBHandle *certdb;
+
+ JAR_Digest *dig;
+ SECItem hexme;
+
+ *length = 0;
+
+ if (attrib == 0 || key == 0)
+ return JAR_ERR_GENERAL;
+
+ if (attrib == jarCertJavaHack)
+ {
+ cert = (CERTCertificate *) NULL;
+ certdb = JAR_open_database();
+
+ if (certdb)
+ {
+#ifdef USE_MOZ_THREAD
+ cert = jar_moz_nickname (certdb, (char*)key);
+#else
+ cert = CERT_FindCertByNickname (certdb, key);
+#endif
+
+ if (cert)
+ {
+ *length = cert->certKey.len;
+
+ *result = (void *) PORT_ZAlloc (*length);
+
+ if (*result)
+ PORT_Memcpy (*result, cert->certKey.data, *length);
+ else
+ return JAR_ERR_MEMORY;
+ }
+ JAR_close_database (certdb);
+ }
+
+ return cert ? 0 : JAR_ERR_GENERAL;
+ }
+
+ if (jar && jar->pkcs7 == 0)
+ return JAR_ERR_GENERAL;
+
+ cert = jar_get_certificate (jar, keylen, key, &status);
+
+ if (cert == NULL || status < 0)
+ return JAR_ERR_GENERAL;
+
+#define SEP " <br> "
+#define SEPLEN (PORT_Strlen(SEP))
+
+ switch (attrib)
+ {
+ case jarCertCompany:
+
+ ret = cert->subjectName;
+
+ /* This is pretty ugly looking but only used
+ here for this one purpose. */
+
+ if (ret)
+ {
+ int retlen = 0;
+
+ char *cer_ou1, *cer_ou2, *cer_ou3;
+ char *cer_cn, *cer_e, *cer_o, *cer_l;
+
+ cer_cn = CERT_GetCommonName (&cert->subject);
+ cer_e = CERT_GetCertEmailAddress (&cert->subject);
+ cer_ou3 = jar_cert_element (ret, "OU=", 3);
+ cer_ou2 = jar_cert_element (ret, "OU=", 2);
+ cer_ou1 = jar_cert_element (ret, "OU=", 1);
+ cer_o = CERT_GetOrgName (&cert->subject);
+ cer_l = CERT_GetCountryName (&cert->subject);
+
+ if (cer_cn) retlen += SEPLEN + PORT_Strlen (cer_cn);
+ if (cer_e) retlen += SEPLEN + PORT_Strlen (cer_e);
+ if (cer_ou1) retlen += SEPLEN + PORT_Strlen (cer_ou1);
+ if (cer_ou2) retlen += SEPLEN + PORT_Strlen (cer_ou2);
+ if (cer_ou3) retlen += SEPLEN + PORT_Strlen (cer_ou3);
+ if (cer_o) retlen += SEPLEN + PORT_Strlen (cer_o);
+ if (cer_l) retlen += SEPLEN + PORT_Strlen (cer_l);
+
+ ret = (char *) PORT_ZAlloc (1 + retlen);
+
+ if (cer_cn) { PORT_Strcpy (ret, cer_cn); PORT_Strcat (ret, SEP); }
+ if (cer_e) { PORT_Strcat (ret, cer_e); PORT_Strcat (ret, SEP); }
+ if (cer_ou1) { PORT_Strcat (ret, cer_ou1); PORT_Strcat (ret, SEP); }
+ if (cer_ou2) { PORT_Strcat (ret, cer_ou2); PORT_Strcat (ret, SEP); }
+ if (cer_ou3) { PORT_Strcat (ret, cer_ou3); PORT_Strcat (ret, SEP); }
+ if (cer_o) { PORT_Strcat (ret, cer_o); PORT_Strcat (ret, SEP); }
+ if (cer_l) PORT_Strcat (ret, cer_l);
+
+ /* return here to avoid unsightly memory leak */
+
+ *result = ret;
+ *length = PORT_Strlen (ret);
+
+ return 0;
+ }
+ break;
+
+ case jarCertCA:
+
+ ret = cert->issuerName;
+
+ if (ret)
+ {
+ int retlen = 0;
+
+ char *cer_ou1, *cer_ou2, *cer_ou3;
+ char *cer_cn, *cer_e, *cer_o, *cer_l;
+
+ /* This is pretty ugly looking but only used
+ here for this one purpose. */
+
+ cer_cn = CERT_GetCommonName (&cert->issuer);
+ cer_e = CERT_GetCertEmailAddress (&cert->issuer);
+ cer_ou3 = jar_cert_element (ret, "OU=", 3);
+ cer_ou2 = jar_cert_element (ret, "OU=", 2);
+ cer_ou1 = jar_cert_element (ret, "OU=", 1);
+ cer_o = CERT_GetOrgName (&cert->issuer);
+ cer_l = CERT_GetCountryName (&cert->issuer);
+
+ if (cer_cn) retlen += SEPLEN + PORT_Strlen (cer_cn);
+ if (cer_e) retlen += SEPLEN + PORT_Strlen (cer_e);
+ if (cer_ou1) retlen += SEPLEN + PORT_Strlen (cer_ou1);
+ if (cer_ou2) retlen += SEPLEN + PORT_Strlen (cer_ou2);
+ if (cer_ou3) retlen += SEPLEN + PORT_Strlen (cer_ou3);
+ if (cer_o) retlen += SEPLEN + PORT_Strlen (cer_o);
+ if (cer_l) retlen += SEPLEN + PORT_Strlen (cer_l);
+
+ ret = (char *) PORT_ZAlloc (1 + retlen);
+
+ if (cer_cn) { PORT_Strcpy (ret, cer_cn); PORT_Strcat (ret, SEP); }
+ if (cer_e) { PORT_Strcat (ret, cer_e); PORT_Strcat (ret, SEP); }
+ if (cer_ou1) { PORT_Strcat (ret, cer_ou1); PORT_Strcat (ret, SEP); }
+ if (cer_ou2) { PORT_Strcat (ret, cer_ou2); PORT_Strcat (ret, SEP); }
+ if (cer_ou3) { PORT_Strcat (ret, cer_ou3); PORT_Strcat (ret, SEP); }
+ if (cer_o) { PORT_Strcat (ret, cer_o); PORT_Strcat (ret, SEP); }
+ if (cer_l) PORT_Strcat (ret, cer_l);
+
+ /* return here to avoid unsightly memory leak */
+
+ *result = ret;
+ *length = PORT_Strlen (ret);
+
+ return 0;
+ }
+
+ break;
+
+ case jarCertSerial:
+
+ ret = CERT_Hexify (&cert->serialNumber, 1);
+ break;
+
+ case jarCertExpires:
+
+ ret = DER_UTCDayToAscii (&cert->validity.notAfter);
+ break;
+
+ case jarCertNickname:
+
+ ret = jar_choose_nickname (cert);
+ break;
+
+ case jarCertFinger:
+
+ dig = JAR_calculate_digest
+ ((char *) cert->derCert.data, cert->derCert.len);
+
+ if (dig)
+ {
+ hexme.len = sizeof (dig->md5);
+ hexme.data = dig->md5;
+ ret = CERT_Hexify (&hexme, 1);
+ }
+ break;
+
+ default:
+
+ return JAR_ERR_GENERAL;
+ }
+
+ *result = ret ? PORT_Strdup (ret) : NULL;
+ *length = ret ? PORT_Strlen (ret) : 0;
+
+ return 0;
+ }
+
+/*
+ * j a r _ c e r t _ e l e m e n t
+ *
+ * Retrieve an element from an x400ish ascii
+ * designator, in a hackish sort of way. The right
+ * thing would probably be to sort AVATags.
+ *
+ */
+
+static char *jar_cert_element (char *name, char *tag, int occ)
+ {
+ if (name && tag)
+ {
+ char *s;
+ int found = 0;
+
+ while (occ--)
+ {
+ if (PORT_Strstr (name, tag))
+ {
+ name = PORT_Strstr (name, tag) + PORT_Strlen (tag);
+ found = 1;
+ }
+ else
+ {
+ name = PORT_Strstr (name, "=");
+ if (name == NULL) return NULL;
+ found = 0;
+ }
+ }
+
+ if (!found) return NULL;
+
+ /* must mangle only the copy */
+ name = PORT_Strdup (name);
+
+ /* advance to next equal */
+ for (s = name; *s && *s != '='; s++)
+ /* yip */ ;
+
+ /* back up to previous comma */
+ while (s > name && *s != ',') s--;
+
+ /* zap the whitespace and return */
+ *s = 0;
+ }
+
+ return name;
+ }
+
+/*
+ * j a r _ c h o o s e _ n i c k n a m e
+ *
+ * Attempt to determine a suitable nickname for
+ * a certificate with a computer-generated "tmpcertxxx"
+ * nickname. It needs to be something a user can
+ * understand, so try a few things.
+ *
+ */
+
+static char *jar_choose_nickname (CERTCertificate *cert)
+ {
+ char *cert_cn;
+ char *cert_o;
+ char *cert_cn_o;
+
+ int cn_o_length;
+
+ /* is the existing name ok */
+
+ if (cert->nickname && PORT_Strncmp (cert->nickname, "tmpcert", 7))
+ return PORT_Strdup (cert->nickname);
+
+ /* we have an ugly name here people */
+
+ /* Try the CN */
+ cert_cn = CERT_GetCommonName (&cert->subject);
+
+ if (cert_cn)
+ {
+ /* check for duplicate nickname */
+
+#ifdef USE_MOZ_THREAD
+ if (jar_moz_nickname (CERT_GetDefaultCertDB(), cert_cn) == NULL)
+#else
+ if (CERT_FindCertByNickname (CERT_GetDefaultCertDB(), cert_cn) == NULL)
+#endif
+ return cert_cn;
+
+ /* Try the CN plus O */
+ cert_o = CERT_GetOrgName (&cert->subject);
+
+ cn_o_length = PORT_Strlen (cert_cn) + 3 + PORT_Strlen (cert_o) + 20;
+ cert_cn_o = (char*)PORT_ZAlloc (cn_o_length);
+
+ PR_snprintf (cert_cn_o, cn_o_length,
+ "%s's %s Certificate", cert_cn, cert_o);
+
+#ifdef USE_MOZ_THREAD
+ if (jar_moz_nickname (CERT_GetDefaultCertDB(), cert_cn_o) == NULL)
+#else
+ if (CERT_FindCertByNickname (CERT_GetDefaultCertDB(), cert_cn_o) == NULL)
+#endif
+ return cert_cn;
+ }
+
+ /* If all that failed, use the ugly nickname */
+ return cert->nickname ? PORT_Strdup (cert->nickname) : NULL;
+ }
+
+/*
+ * J A R _ c e r t _ h t m l
+ *
+ * Return an HTML representation of the certificate
+ * designated by the given fingerprint, in specified style.
+ *
+ * JAR is optional, but supply it if you can in order
+ * to optimize.
+ *
+ */
+
+char *JAR_cert_html
+ (JAR *jar, int style, long keylen, void *key, int *result)
+ {
+ char *html;
+ CERTCertificate *cert;
+
+ *result = -1;
+
+ if (style != 0)
+ return NULL;
+
+ cert = jar_get_certificate (jar, keylen, key, result);
+
+ if (cert == NULL || *result < 0)
+ return NULL;
+
+ *result = 0;
+
+ html = CERT_HTMLCertInfo (cert, /* show images */ PR_TRUE,
+ /*show issuer*/PR_TRUE);
+
+ if (html == NULL)
+ *result = -1;
+
+ return html;
+ }
+
+/*
+ * J A R _ s t a s h _ c e r t
+ *
+ * Stash the certificate pointed to by this
+ * fingerprint, in persistent storage somewhere.
+ *
+ */
+
+extern int PR_CALLBACK JAR_stash_cert
+ (JAR *jar, long keylen, void *key)
+ {
+ int result = 0;
+
+ char *nickname;
+ CERTCertTrust trust;
+
+ CERTCertDBHandle *certdb;
+ CERTCertificate *cert, *newcert;
+
+ cert = jar_get_certificate (jar, keylen, key, &result);
+
+ if (result < 0)
+ return result;
+
+ if (cert == NULL)
+ return JAR_ERR_GENERAL;
+
+ if ((certdb = JAR_open_database()) == NULL)
+ return JAR_ERR_GENERAL;
+
+ /* Attempt to give a name to the newish certificate */
+ nickname = jar_choose_nickname (cert);
+
+#ifdef USE_MOZ_THREAD
+ newcert = jar_moz_nickname (certdb, nickname);
+#else
+ newcert = CERT_FindCertByNickname (certdb, nickname);
+#endif
+
+ if (newcert && newcert->isperm)
+ {
+ /* already in permanant database */
+ return 0;
+ }
+
+ if (newcert) cert = newcert;
+
+ /* FIX, since FindCert returns a bogus dbhandle
+ set it ourselves */
+
+ cert->dbhandle = certdb;
+
+#if 0
+ nickname = cert->subjectName;
+ if (nickname)
+ {
+ /* Not checking for a conflict here. But this should
+ be a new cert or it would have been found earlier. */
+
+ nickname = jar_cert_element (nickname, "CN=", 1);
+
+ if (SEC_CertNicknameConflict (nickname, cert->dbhandle))
+ {
+ /* conflict */
+ nickname = PORT_Realloc (&nickname, PORT_Strlen (nickname) + 3);
+
+ /* Beyond one copy, there are probably serious problems
+ so we will stop at two rather than counting.. */
+
+ PORT_Strcat (nickname, " #2");
+ }
+ }
+#endif
+
+ if (nickname != NULL)
+ {
+ PORT_Memset ((void *) &trust, 0, sizeof(trust));
+
+#ifdef USE_MOZ_THREAD
+ if (jar_moz_perm (cert, nickname, &trust) != SECSuccess)
+#else
+ if (CERT_AddTempCertToPerm (cert, nickname, &trust) != SECSuccess)
+#endif
+ {
+ /* XXX might want to call PORT_GetError here */
+ result = JAR_ERR_GENERAL;
+ }
+ }
+
+ JAR_close_database (certdb);
+
+ return result;
+ }
+
+/*
+ * J A R _ f e t c h _ c e r t
+ *
+ * Given an opaque identifier of a certificate,
+ * return the full certificate.
+ *
+ * The new function, which retrieves by key.
+ *
+ */
+
+void *JAR_fetch_cert (long length, void *key)
+ {
+ SECItem seckey;
+ CERTCertificate *cert = NULL;
+
+ CERTCertDBHandle *certdb;
+
+ certdb = JAR_open_database();
+
+ if (certdb)
+ {
+ seckey.len = length;
+ seckey.data = (unsigned char*)key;
+
+#ifdef USE_MOZ_THREAD
+ cert = jar_moz_certkey (certdb, &seckey);
+#else
+ cert = CERT_FindCertByKey (certdb, &seckey);
+#endif
+
+ JAR_close_database (certdb);
+ }
+
+ return (void *) cert;
+ }
+
+/*
+ * j a r _ g e t _ m f _ d i g e s t
+ *
+ * Retrieve a corresponding saved digest over a section
+ * of the main manifest file.
+ *
+ */
+
+static JAR_Digest *jar_get_mf_digest (JAR *jar, char *pathname)
+ {
+ JAR_Item *it;
+
+ JAR_Digest *dig;
+
+ ZZLink *link;
+ ZZList *list;
+
+ list = jar->manifest;
+
+ if (ZZ_ListEmpty (list))
+ return NULL;
+
+ for (link = ZZ_ListHead (list);
+ !ZZ_ListIterDone (list, link);
+ link = link->next)
+ {
+ it = link->thing;
+ if (it->type == jarTypeSect
+ && it->pathname && !PORT_Strcmp (it->pathname, pathname))
+ {
+ dig = (JAR_Digest *) it->data;
+ return dig;
+ }
+ }
+
+ return NULL;
+ }
+
+/*
+ * j a r _ b a s e n a m e
+ *
+ * Return the basename -- leading components of path stripped off,
+ * extension ripped off -- of a path.
+ *
+ */
+
+static char *jar_basename (const char *path)
+ {
+ char *pith, *e, *basename, *ext;
+
+ if (path == NULL)
+ return PORT_Strdup ("");
+
+ pith = PORT_Strdup (path);
+
+ basename = pith;
+
+ while (1)
+ {
+ for (e = basename; *e && *e != '/' && *e != '\\'; e++)
+ /* yip */ ;
+ if (*e)
+ basename = ++e;
+ else
+ break;
+ }
+
+ if ((ext = PORT_Strrchr (basename, '.')) != NULL)
+ *ext = 0;
+
+ /* We already have the space allocated */
+ PORT_Strcpy (pith, basename);
+
+ return pith;
+ }
+
+/*
+ * + + + + + + + + + + + + + + +
+ *
+ * CRYPTO ROUTINES FOR JAR
+ *
+ * The following functions are the cryptographic
+ * interface to PKCS7 for Jarnatures.
+ *
+ * + + + + + + + + + + + + + + +
+ *
+ */
+
+/*
+ * j a r _ c a t c h _ b y t e s
+ *
+ * In the event signatures contain enveloped data, it will show up here.
+ * But note that the lib/pkcs7 routines aren't ready for it.
+ *
+ */
+
+static void jar_catch_bytes
+ (void *arg, const char *buf, unsigned long len)
+ {
+ /* Actually this should never be called, since there is
+ presumably no data in the signature itself. */
+ }
+
+/*
+ * j a r _ v a l i d a t e _ p k c s 7
+ *
+ * Validate (and decode, if necessary) a binary pkcs7
+ * signature in DER format.
+ *
+ */
+
+static int jar_validate_pkcs7
+ (JAR *jar, JAR_Signer *signer, char *data, long length)
+ {
+ SECItem detdig;
+
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7DecoderContext *dcx;
+
+ int status = 0;
+ char *errstring = NULL;
+
+ PORT_Assert( jar != NULL && signer != NULL );
+
+ if (jar == NULL || signer == NULL)
+ return JAR_ERR_ORDER;
+
+ signer->valid = JAR_ERR_SIG;
+
+ /* We need a context if we can get one */
+
+#ifdef MOZILLA_CLIENT
+ if (jar->mw == NULL) {
+ JAR_set_context (jar, NULL);
+ }
+#endif
+
+
+ dcx = SEC_PKCS7DecoderStart
+ (jar_catch_bytes, NULL /*cb_arg*/, NULL /*getpassword*/, jar->mw,
+ NULL, NULL, NULL);
+
+ if (dcx != NULL)
+ {
+ SEC_PKCS7DecoderUpdate (dcx, data, length);
+ cinfo = SEC_PKCS7DecoderFinish (dcx);
+ }
+
+ if (cinfo == NULL)
+ {
+ /* strange pkcs7 failure */
+ return JAR_ERR_PK7;
+ }
+
+ if (SEC_PKCS7ContentIsEncrypted (cinfo))
+ {
+ /* content was encrypted, fail */
+ return JAR_ERR_PK7;
+ }
+
+ if (SEC_PKCS7ContentIsSigned (cinfo) == PR_FALSE)
+ {
+ /* content was not signed, fail */
+ return JAR_ERR_PK7;
+ }
+
+ PORT_SetError (0);
+
+ /* use SHA1 only */
+
+ detdig.len = SHA1_LENGTH;
+ detdig.data = signer->digest->sha1;
+
+#ifdef USE_MOZ_THREAD
+ if (jar_moz_verify
+ (cinfo, certUsageObjectSigner, &detdig, HASH_AlgSHA1, PR_FALSE)==
+ SECSuccess)
+#else
+ if (SEC_PKCS7VerifyDetachedSignature
+ (cinfo, certUsageObjectSigner, &detdig, HASH_AlgSHA1, PR_FALSE)==
+ PR_TRUE)
+#endif
+ {
+ /* signature is valid */
+ signer->valid = 0;
+ jar_gather_signers (jar, signer, cinfo);
+ }
+ else
+ {
+ status = PORT_GetError();
+
+ PORT_Assert( status < 0 );
+ if (status >= 0) status = JAR_ERR_SIG;
+
+ jar->valid = status;
+ signer->valid = status;
+
+ errstring = JAR_get_error (status);
+ /*XP_TRACE(("JAR signature invalid (reason %d = %s)", status, errstring));*/
+ }
+
+ jar->pkcs7 = PR_TRUE;
+ signer->pkcs7 = PR_TRUE;
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ return status;
+ }
+
+/*
+ * j a r _ g a t h e r _ s i g n e r s
+ *
+ * Add the single signer of this signature to the
+ * certificate linked list.
+ *
+ */
+
+static int jar_gather_signers
+ (JAR *jar, JAR_Signer *signer, SEC_PKCS7ContentInfo *cinfo)
+ {
+ int result;
+
+ CERTCertificate *cert;
+ CERTCertDBHandle *certdb;
+
+ SEC_PKCS7SignedData *sdp;
+ SEC_PKCS7SignerInfo **pksigners, *pksigner;
+
+ sdp = cinfo->content.signedData;
+
+ if (sdp == NULL)
+ return JAR_ERR_PK7;
+
+ pksigners = sdp->signerInfos;
+
+ /* permit exactly one signer */
+
+ if (pksigners == NULL || pksigners [0] == NULL || pksigners [1] != NULL)
+ return JAR_ERR_PK7;
+
+ pksigner = *pksigners;
+ cert = pksigner->cert;
+
+ if (cert == NULL)
+ return JAR_ERR_PK7;
+
+ certdb = JAR_open_database();
+
+ if (certdb == NULL)
+ return JAR_ERR_GENERAL;
+
+ result = jar_add_cert (jar, signer, jarTypeSign, cert);
+
+ JAR_close_database (certdb);
+
+ return result;
+ }
+
+/*
+ * j a r _ o p e n _ d a t a b a s e
+ *
+ * Open the certificate database,
+ * for use by JAR functions.
+ *
+ */
+
+CERTCertDBHandle *JAR_open_database (void)
+ {
+ int keepcerts = 0;
+ CERTCertDBHandle *certdb;
+
+ /* local_certdb will only be used if calling from a command line tool */
+ static CERTCertDBHandle local_certdb;
+
+ certdb = CERT_GetDefaultCertDB();
+
+ if (certdb == NULL)
+ {
+ if (CERT_OpenCertDBFilename (&local_certdb, NULL, (PRBool)!keepcerts) !=
+ SECSuccess)
+ {
+ return NULL;
+ }
+ certdb = &local_certdb;
+ }
+
+ return certdb;
+ }
+
+/*
+ * j a r _ c l o s e _ d a t a b a s e
+ *
+ * Close the certificate database.
+ * For use by JAR functions.
+ *
+ */
+
+int JAR_close_database (CERTCertDBHandle *certdb)
+ {
+ CERTCertDBHandle *defaultdb;
+
+ /* This really just retrieves the handle, nothing more */
+ defaultdb = CERT_GetDefaultCertDB();
+
+ /* If there is no default db, it means we opened
+ the permanent database for some reason */
+
+ if (defaultdb == NULL && certdb != NULL)
+ CERT_ClosePermCertDB (certdb);
+
+ return 0;
+ }
+
+/*
+ * j a r _ g e t _ c e r t i f i c a t e
+ *
+ * Return the certificate referenced
+ * by a given fingerprint, or NULL if not found.
+ * Error code is returned in result.
+ *
+ */
+
+static CERTCertificate *jar_get_certificate
+ (JAR *jar, long keylen, void *key, int *result)
+ {
+ int found = 0;
+
+ JAR_Item *it;
+ JAR_Cert *fing;
+
+ JAR_Context *ctx;
+
+ if (jar == NULL)
+ {
+ void *cert;
+ cert = JAR_fetch_cert (keylen, key);
+ *result = (cert == NULL) ? JAR_ERR_GENERAL : 0;
+ return (CERTCertificate *) cert;
+ }
+
+ ctx = JAR_find (jar, NULL, jarTypeSign);
+
+ while (JAR_find_next (ctx, &it) >= 0)
+ {
+ fing = (JAR_Cert *) it->data;
+
+ if (keylen != fing->length)
+ continue;
+
+ PORT_Assert( keylen < 0xFFFF );
+ if (!PORT_Memcmp (fing->key, key, keylen))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ JAR_find_end (ctx);
+
+ if (found == 0)
+ {
+ *result = JAR_ERR_GENERAL;
+ return NULL;
+ }
+
+ *result = 0;
+ return fing->cert;
+ }
+
+/*
+ * j a r _ s i g n a l
+ *
+ * Nonfatal errors come here to callback Java.
+ *
+ */
+
+static int jar_signal
+ (int status, JAR *jar, const char *metafile, char *pathname)
+ {
+ char *errstring;
+
+ errstring = JAR_get_error (status);
+
+ if (jar->signal)
+ {
+ (*jar->signal) (status, jar, metafile, pathname, errstring);
+ return 0;
+ }
+
+ return status;
+ }
+
+/*
+ * j a r _ a p p e n d
+ *
+ * Tack on an element to one of a JAR's linked
+ * lists, with rudimentary error handling.
+ *
+ */
+
+int jar_append (ZZList *list, int type,
+ char *pathname, void *data, size_t size)
+ {
+ JAR_Item *it;
+ ZZLink *entity;
+
+ it = (JAR_Item*)PORT_ZAlloc (sizeof (JAR_Item));
+
+ if (it == NULL)
+ goto loser;
+
+ if (pathname)
+ {
+ it->pathname = PORT_Strdup (pathname);
+ if (it->pathname == NULL)
+ goto loser;
+ }
+
+ it->type = (jarType)type;
+ it->data = (unsigned char *) data;
+ it->size = size;
+
+ entity = ZZ_NewLink (it);
+
+ if (entity)
+ {
+ ZZ_AppendLink (list, entity);
+ return 0;
+ }
+
+loser:
+
+ if (it)
+ {
+ if (it->pathname) PORT_Free (it->pathname);
+ PORT_Free (it);
+ }
+
+ return JAR_ERR_MEMORY;
+ }
+
+/*
+ * W I N 1 6 s t u f f
+ *
+ * These functions possibly belong in xp_mem.c, they operate
+ * on huge string pointers for win16.
+ *
+ */
+
+#if defined(XP_WIN16)
+int xp_HUGE_STRNCASECMP (char ZHUGEP *buf, char *key, int len)
+ {
+ while (len--)
+ {
+ char c1, c2;
+
+ c1 = *buf++;
+ c2 = *key++;
+
+ if (c1 >= 'a' && c1 <= 'z') c1 -= ('a' - 'A');
+ if (c2 >= 'a' && c2 <= 'z') c2 -= ('a' - 'A');
+
+ if (c1 != c2)
+ return (c1 < c2) ? -1 : 1;
+ }
+ return 0;
+ }
+
+size_t xp_HUGE_STRLEN (char ZHUGEP *s)
+ {
+ size_t len = 0L;
+ while (*s++) len++;
+ return len;
+ }
+
+char *xp_HUGE_STRCPY (char *to, char ZHUGEP *from)
+ {
+ char *ret = to;
+
+ while (*from)
+ *to++ = *from++;
+ *to = 0;
+
+ return ret;
+ }
+#endif
diff --git a/security/nss/lib/jar/jzconf.h b/security/nss/lib/jar/jzconf.h
new file mode 100644
index 000000000..278aaa5d5
--- /dev/null
+++ b/security/nss/lib/jar/jzconf.h
@@ -0,0 +1,190 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32) || defined(XP_OS2)) && !defined(STDC)
+# define STDC
+#endif
+#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC)
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR __far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR __far
+# endif
+#endif
+#ifndef FAR
+# define FAR
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
+ /* Borland C/C++ ignores FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef MOZILLA_CLIENT
+#include "prtypes.h"
+#else
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
+# include <windows.h>
+# define EXPORT WINAPI
+#else
+# define EXPORT
+#endif
+
+#define PR_PUBLIC_API(type) type
+
+#endif /* MOZILLA_CLIENT */
+
+#endif /* _ZCONF_H */
diff --git a/security/nss/lib/jar/jzlib.h b/security/nss/lib/jar/jzlib.h
new file mode 100644
index 000000000..b216f00a3
--- /dev/null
+++ b/security/nss/lib/jar/jzlib.h
@@ -0,0 +1,892 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.0.4, Jul 24th, 1996.
+
+ Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+/* This file was modified since it was taken from the zlib distribution */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "zconf.h"
+
+#define ZLIB_VERSION "1.0.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern const char *) zlibVersion (void);
+#else
+extern const char * EXPORT zlibVersion OF((void));
+#endif
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+extern int EXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflate (z_streamp strm, int flush);
+#else
+extern int EXPORT deflate OF((z_streamp strm, int flush));
+#endif
+/*
+ Performs one or both of the following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
+ block is terminated and flushed to the output buffer so that the
+ decompressor can get all input data available so far. For method 9, a future
+ variant on method 8, the current block will be flushed but not terminated.
+ Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
+ output is byte aligned (the compressor can clear its internal bit buffer)
+ and the current block is always terminated; this can be useful if the
+ compressor has to be restarted from scratch after an interruption (in which
+ case the internal state of the compressor may be lost).
+ If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
+ special marker is output and the compression dictionary is discarded; this
+ is useful to allow the decompressor to synchronize if one compressed block
+ has been damaged (see inflateSync below). Flushing degrades compression and
+ so should be used only when necessary. Using Z_FULL_FLUSH too often can
+ seriously degrade the compression. If deflate returns with avail_out == 0,
+ this function must be called again with the same value of the flush
+ parameter and more output space (updated avail_out), until the flush is
+ complete (deflate returns with non-zero avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateEnd (z_streamp strm);
+#else
+extern int EXPORT deflateEnd OF((z_streamp strm));
+#endif
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+extern int EXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
+ allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
+ with the version assumed by the caller. msg is set to null if there is no
+ error message. inflateInit does not perform any decompression: this will be
+ done by inflate().
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflate (z_streamp strm, int flush);
+#else
+extern int EXPORT inflate OF((z_streamp strm, int flush));
+#endif
+/*
+ Performs one or both of the following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_PARTIAL_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ inflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if the end of the
+ compressed data has been reached and all uncompressed output has been
+ produced, Z_NEED_DICT if a preset dictionary is needed at this point (see
+ inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
+ Z_STREAM_ERROR if the stream structure was inconsistent (for example if
+ next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in
+ the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the
+ application may then call inflateSync to look for a good compression block.
+ In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
+ dictionary chosen by the compressor.
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateEnd (z_streamp strm);
+#else
+extern int EXPORT inflateEnd OF((z_streamp strm));
+#endif
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+extern int EXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library. (Method 9 will allow a 64K history buffer and
+ partial block flushes.)
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library (the value 16 will be allowed for method 9). Larger
+ values of this parameter result in better compression at the expense of
+ memory usage. The default value is 15 if deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ If next_in is not null, the library will use this buffer to hold also
+ some history information; the buffer must either hold the entire input
+ data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
+ is null, the library will allocate its own history buffer (and leave next_in
+ null). next_out need not be provided here but must be provided by the
+ application for the next call of deflate().
+
+ If the history buffer is provided by the application, next_in must
+ must never be changed by the application since the compressor maintains
+ information inside this buffer from call to call; the application
+ must provide more input only by increasing avail_in. next_in is always
+ reset by the library in this case.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ an invalid method). msg is set to null if there is no error message.
+ deflateInit2 does not perform any compression: this will be done by
+ deflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateSetDictionary (z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+#else
+extern int EXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+#endif
+/*
+ Initializes the compression dictionary (history buffer) from the given
+ byte sequence without producing any compressed output. This function must
+ be called immediately after deflateInit or deflateInit2, before any call
+ of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and
+ can be predicted with good accuracy; the data can then be compressed better
+ than with the default empty dictionary. In this version of the library,
+ only the last 32K bytes of the dictionary are used.
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state
+ is inconsistent (for example if deflate has already been called for this
+ stream). deflateSetDictionary does not perform any compression: this will
+ be done by deflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateCopy (z_streamp dest, z_streamp source);
+#else
+extern int EXPORT deflateCopy OF((z_streamp dest, z_streamp source));
+#endif
+/*
+ Sets the destination stream as a complete copy of the source stream. If
+ the source stream is using an application-supplied history buffer, a new
+ buffer is allocated for the destination stream. The compressed output
+ buffer is always application-supplied. It's the responsibility of the
+ application to provide the correct values of next_out and avail_out for the
+ next call of deflate.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateReset (z_streamp strm);
+#else
+extern int EXPORT deflateReset OF((z_streamp strm));
+#endif
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateParams (z_streamp strm, int level, int strategy);
+#else
+extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
+#endif
+/*
+ Dynamically update the compression level and compression strategy.
+ This can be used to switch between compression and straight copy of
+ the input data, or to switch to a different kind of input data requiring
+ a different strategy. If the compression level is changed, the input
+ available so far is compressed with the old level (and may be flushed);
+ the new level will take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+extern int EXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with more compression options. The
+ fields next_out, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library (the value 16 will be allowed soon). The
+ default value is 15 if inflateInit is used instead. If a compressed stream
+ with a larger window size is given as input, inflate() will return with
+ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<<windowBits bytes. If next_out is null, the
+ library will allocate its own buffer (and leave next_out null). next_in
+ need not be provided here but must be provided by the application for the
+ next call of inflate().
+
+ If the history buffer is provided by the application, next_out must
+ never be changed by the application since the decompressor maintains
+ history information inside this buffer from call to call; the application
+ can only reset next_out to the beginning of the history buffer when
+ avail_out is zero and all output has been consumed.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ windowBits < 8). msg is set to null if there is no error message.
+ inflateInit2 does not perform any decompression: this will be done by
+ inflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateSetDictionary (z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+#else
+extern int EXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+#endif
+/*
+ Initializes the decompression dictionary (history buffer) from the given
+ uncompressed byte sequence. This function must be called immediately after
+ a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen
+ by the compressor can be determined from the Adler32 value returned by this
+ call of inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateSync (z_streamp strm);
+#else
+extern int EXPORT inflateSync OF((z_streamp strm));
+#endif
+/*
+ Skips invalid compressed data until the special marker (see deflate()
+ above) can be found, or until all available input is skipped. No output
+ is provided.
+
+ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no marker has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateReset (z_streamp strm);
+#else
+extern int EXPORT inflateReset OF((z_streamp strm));
+#endif
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level, window size,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) compress (Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+#else
+extern int EXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+#endif
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) uncompress (Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+#else
+extern int EXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+#endif
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzopen (const char *path, const char *mode);
+#else
+extern gzFile EXPORT gzopen OF((const char *path, const char *mode));
+#endif
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9"). gzopen can be used to read a file which is not in gzip format;
+ in this case gzread will directly read from the file without decompression.
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzdopen (int fd, const char *mode);
+#else
+extern gzFile EXPORT gzdopen OF((int fd, const char *mode));
+#endif
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzread (gzFile file, voidp buf, unsigned len);
+#else
+extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+#endif
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzwrite (gzFile file, const voidp buf, unsigned len);
+#else
+extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
+#endif
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzflush (gzFile file, int flush);
+#else
+extern int EXPORT gzflush OF((gzFile file, int flush));
+#endif
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzclose (gzFile file);
+#else
+extern int EXPORT gzclose OF((gzFile file));
+#endif
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern const char *) gzerror (gzFile file, int *errnum);
+#else
+extern const char * EXPORT gzerror OF((gzFile file, int *errnum));
+#endif
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern uLong) adler32 (uLong adler, const Bytef *buf, uInt len);
+#else
+extern uLong EXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+#endif
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern uLong) crc32 (uLong crc, const Bytef *buf, uInt len);
+#else
+extern uLong EXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+#endif
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateInit_ (z_streamp strm, int level, const char *version,
+ int stream_size);
+PR_PUBLIC_API(extern int) inflateInit_ (z_streamp strm, const char *version,
+ int stream_size);
+PR_PUBLIC_API(extern int) deflateInit2_ (z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size);
+PR_PUBLIC_API(extern int) inflateInit2_ (z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+#else
+extern int EXPORT deflateInit_ OF((z_streamp strm, int level, const char *version,
+ int stream_size));
+extern int EXPORT inflateInit_ OF((z_streamp strm, const char *version,
+ int stream_size));
+extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size));
+extern int EXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#endif /* MOZILLA_CLIENT */
+
+
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/security/nss/lib/jar/manifest.mn b/security/nss/lib/jar/manifest.mn
new file mode 100644
index 000000000..4ba86cd7d
--- /dev/null
+++ b/security/nss/lib/jar/manifest.mn
@@ -0,0 +1,51 @@
+# 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.
+
+MODULE = security
+
+LIBRARY_NAME = jar
+
+CORE_DEPTH = ../../..
+
+CSRCS = \
+ jarver.c \
+ jarsign.c \
+ jar.c \
+ jar-ds.c \
+ jarfile.c \
+ jarevil.c \
+ jarjart.c \
+ jarint.c \
+ $(NULL)
+
+REQUIRES = security dbm
+
+EXPORTS = jar.h jar-ds.h jarfile.h