diff options
author | relyea%netscape.com <devnull@localhost> | 2000-03-31 20:13:40 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2000-03-31 20:13:40 +0000 |
commit | 9502869e82d4f3ce26b292263e1c626dca3a34f3 (patch) | |
tree | 4d0f8ab157505b57c13a5e2bdf979560ab751527 /security/nss/lib/jar | |
parent | 222a52dab759085f56dcb6588b69a6a937d82aa2 (diff) | |
download | nss-hg-9502869e82d4f3ce26b292263e1c626dca3a34f3.tar.gz |
Initial NSS Open Source checkin
Diffstat (limited to 'security/nss/lib/jar')
-rw-r--r-- | security/nss/lib/jar/Makefile | 39 | ||||
-rw-r--r-- | security/nss/lib/jar/config.mk | 44 | ||||
-rw-r--r-- | security/nss/lib/jar/jar-ds.c | 70 | ||||
-rw-r--r-- | security/nss/lib/jar/jar-ds.h | 106 | ||||
-rw-r--r-- | security/nss/lib/jar/jar.c | 833 | ||||
-rw-r--r-- | security/nss/lib/jar/jar.h | 477 | ||||
-rw-r--r-- | security/nss/lib/jar/jarevil.c | 571 | ||||
-rw-r--r-- | security/nss/lib/jar/jarevil.h | 76 | ||||
-rw-r--r-- | security/nss/lib/jar/jarfile.c | 1149 | ||||
-rw-r--r-- | security/nss/lib/jar/jarfile.h | 114 | ||||
-rw-r--r-- | security/nss/lib/jar/jarint.c | 81 | ||||
-rw-r--r-- | security/nss/lib/jar/jarint.h | 116 | ||||
-rw-r--r-- | security/nss/lib/jar/jarjart.c | 354 | ||||
-rw-r--r-- | security/nss/lib/jar/jarjart.h | 72 | ||||
-rw-r--r-- | security/nss/lib/jar/jarnav.c | 107 | ||||
-rw-r--r-- | security/nss/lib/jar/jarsign.c | 376 | ||||
-rw-r--r-- | security/nss/lib/jar/jarver.c | 2029 | ||||
-rw-r--r-- | security/nss/lib/jar/jzconf.h | 190 | ||||
-rw-r--r-- | security/nss/lib/jar/jzlib.h | 892 | ||||
-rw-r--r-- | security/nss/lib/jar/manifest.mn | 51 |
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 |