Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / jar / jarver.c
blobd8753dc1dd8015182cbc42baf8290ec871dc38e2
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * JARVER
40 * Jarnature Parsing & Verification
43 #include "nssrenam.h"
44 #include "jar.h"
45 #include "jarint.h"
46 #include "certdb.h"
47 #include "certt.h"
48 #include "secpkcs7.h"
50 /*#include "cdbhdl.h" */
51 #include "secder.h"
53 /* to use huge pointers in win16 */
55 #define xp_HUGE_MEMCPY PORT_Memcpy
56 #define xp_HUGE_STRCPY PORT_Strcpy
57 #define xp_HUGE_STRLEN PORT_Strlen
58 #define xp_HUGE_STRNCASECMP PORT_Strncasecmp
60 /* from certdb.h */
61 #define CERTDB_USER (1<<6)
63 #define SZ 512
65 static int jar_validate_pkcs7
66 (JAR *jar, JAR_Signer *signer, char *data, long length);
68 static void jar_catch_bytes
69 (void *arg, const char *buf, unsigned long len);
71 static int jar_gather_signers
72 (JAR *jar, JAR_Signer *signer, SEC_PKCS7ContentInfo *cinfo);
74 static char ZHUGEP *jar_eat_line
75 (int lines, int eating, char ZHUGEP *data, long *len);
77 static JAR_Digest *jar_digest_section
78 (char ZHUGEP *manifest, long length);
80 static JAR_Digest *jar_get_mf_digest (JAR *jar, char *path);
82 static int jar_parse_digital_signature
83 (char *raw_manifest, JAR_Signer *signer, long length, JAR *jar);
85 static int jar_add_cert
86 (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert);
88 static CERTCertificate *jar_get_certificate
89 (JAR *jar, long keylen, void *key, int *result);
91 static char *jar_cert_element (char *name, char *tag, int occ);
93 static char *jar_choose_nickname (CERTCertificate *cert);
95 static char *jar_basename (const char *path);
97 static int jar_signal
98 (int status, JAR *jar, const char *metafile, char *pathname);
100 #ifdef DEBUG
101 static int jar_insanity_check (char ZHUGEP *data, long length);
102 #endif
104 int jar_parse_mf
105 (JAR *jar, char ZHUGEP *raw_manifest,
106 long length, const char *path, const char *url);
108 int jar_parse_sf
109 (JAR *jar, char ZHUGEP *raw_manifest,
110 long length, const char *path, const char *url);
112 int jar_parse_sig
113 (JAR *jar, const char *path, char ZHUGEP *raw_manifest, long length);
115 int jar_parse_any
116 (JAR *jar, int type, JAR_Signer *signer, char ZHUGEP *raw_manifest,
117 long length, const char *path, const char *url);
119 static int jar_internal_digest
120 (JAR *jar, const char *path, char *x_name, JAR_Digest *dig);
123 * J A R _ p a r s e _ m a n i f e s t
125 * Pass manifest files to this function. They are
126 * decoded and placed into internal representations.
128 * Accepts both signature and manifest files. Use
129 * the same "jar" for both.
133 int JAR_parse_manifest
134 (JAR *jar, char ZHUGEP *raw_manifest,
135 long length, const char *path, const char *url)
137 int filename_free = 0;
139 /* fill in the path, if supplied. This is a the location
140 of the jar file on disk, if known */
142 if (jar->filename == NULL && path)
144 jar->filename = PORT_Strdup (path);
145 if (jar->filename == NULL)
146 return JAR_ERR_MEMORY;
147 filename_free = 1;
150 /* fill in the URL, if supplied. This is the place
151 from which the jar file was retrieved. */
153 if (jar->url == NULL && url)
155 jar->url = PORT_Strdup (url);
156 if (jar->url == NULL)
158 if (filename_free)
160 PORT_Free (jar->filename);
162 return JAR_ERR_MEMORY;
166 /* Determine what kind of file this is from the META-INF
167 directory. It could be MF, SF, or a binary RSA/DSA file */
169 if (!xp_HUGE_STRNCASECMP (raw_manifest, "Manifest-Version:", 17))
171 return jar_parse_mf (jar, raw_manifest, length, path, url);
173 else if (!xp_HUGE_STRNCASECMP (raw_manifest, "Signature-Version:", 18))
175 return jar_parse_sf (jar, raw_manifest, length, path, url);
177 else
179 /* This is probably a binary signature */
180 return jar_parse_sig (jar, path, raw_manifest, length);
185 * j a r _ p a r s e _ s i g
187 * Pass some manner of RSA or DSA digital signature
188 * on, after checking to see if it comes at an appropriate state.
192 int jar_parse_sig
193 (JAR *jar, const char *path, char ZHUGEP *raw_manifest, long length)
195 JAR_Signer *signer;
196 int status = JAR_ERR_ORDER;
198 if (length <= 128)
200 /* signature is way too small */
201 return JAR_ERR_SIG;
204 /* make sure that MF and SF have already been processed */
206 if (jar->globalmeta == NULL)
207 return JAR_ERR_ORDER;
209 /* Determine whether or not this RSA file has
210 has an associated SF file */
212 if (path)
214 char *owner;
215 owner = jar_basename (path);
217 if (owner == NULL)
218 return JAR_ERR_MEMORY;
220 signer = jar_get_signer (jar, owner);
222 PORT_Free (owner);
224 else
225 signer = jar_get_signer (jar, "*");
227 if (signer == NULL)
228 return JAR_ERR_ORDER;
231 /* Do not pass a huge pointer to this function,
232 since the underlying security code is unaware. We will
233 never pass >64k through here. */
235 if (length > 64000)
237 /* this digital signature is way too big */
238 return JAR_ERR_SIG;
241 /* don't expense unneeded calloc overhead on non-win16 */
242 status = jar_parse_digital_signature
243 (raw_manifest, signer, length, jar);
245 return status;
249 * j a r _ p a r s e _ m f
251 * Parse the META-INF/manifest.mf file, whose
252 * information applies to all signers.
256 int jar_parse_mf
257 (JAR *jar, char ZHUGEP *raw_manifest,
258 long length, const char *path, const char *url)
260 if (jar->globalmeta)
262 /* refuse a second manifest file, if passed for some reason */
263 return JAR_ERR_ORDER;
267 /* remember a digest for the global section */
269 jar->globalmeta = jar_digest_section (raw_manifest, length);
271 if (jar->globalmeta == NULL)
272 return JAR_ERR_MEMORY;
275 return jar_parse_any
276 (jar, jarTypeMF, NULL, raw_manifest, length, path, url);
280 * j a r _ p a r s e _ s f
282 * Parse META-INF/xxx.sf, a digitally signed file
283 * pointing to a subset of MF sections.
287 int jar_parse_sf
288 (JAR *jar, char ZHUGEP *raw_manifest,
289 long length, const char *path, const char *url)
291 JAR_Signer *signer = NULL;
292 int status = JAR_ERR_MEMORY;
294 if (jar->globalmeta == NULL)
296 /* It is a requirement that the MF file be passed before the SF file */
297 return JAR_ERR_ORDER;
300 signer = JAR_new_signer();
302 if (signer == NULL)
303 goto loser;
305 if (path)
307 signer->owner = jar_basename (path);
308 if (signer->owner == NULL)
309 goto loser;
313 /* check for priors. When someone doctors a jar file
314 to contain identical path entries, prevent the second
315 one from affecting JAR functions */
317 if (jar_get_signer (jar, signer->owner))
319 /* someone is trying to spoof us */
320 status = JAR_ERR_ORDER;
321 goto loser;
325 /* remember its digest */
327 signer->digest = JAR_calculate_digest (raw_manifest, length);
329 if (signer->digest == NULL)
330 goto loser;
332 /* Add this signer to the jar */
334 ADDITEM (jar->signers, jarTypeOwner,
335 signer->owner, signer, sizeof (JAR_Signer));
338 return jar_parse_any
339 (jar, jarTypeSF, signer, raw_manifest, length, path, url);
341 loser:
343 if (signer)
344 JAR_destroy_signer (signer);
346 return status;
350 * j a r _ p a r s e _ a n y
352 * Parse a MF or SF manifest file.
356 int jar_parse_any
357 (JAR *jar, int type, JAR_Signer *signer, char ZHUGEP *raw_manifest,
358 long length, const char *path, const char *url)
360 int status;
362 long raw_len;
364 JAR_Digest *dig, *mfdig = NULL;
366 char line [SZ];
367 char x_name [SZ], x_md5 [SZ], x_sha [SZ];
369 char *x_info;
371 char *sf_md5 = NULL, *sf_sha1 = NULL;
373 *x_name = 0;
374 *x_md5 = 0;
375 *x_sha = 0;
377 PORT_Assert( length > 0 );
378 raw_len = length;
380 #ifdef DEBUG
381 if ((status = jar_insanity_check (raw_manifest, raw_len)) < 0)
382 return status;
383 #endif
386 /* null terminate the first line */
387 raw_manifest = jar_eat_line (0, PR_TRUE, raw_manifest, &raw_len);
390 /* skip over the preliminary section */
391 /* This is one section at the top of the file with global metainfo */
393 while (raw_len)
395 JAR_Metainfo *met;
397 raw_manifest = jar_eat_line (1, PR_TRUE, raw_manifest, &raw_len);
398 if (!*raw_manifest) break;
400 met = (JAR_Metainfo*)PORT_ZAlloc (sizeof (JAR_Metainfo));
401 if (met == NULL)
402 return JAR_ERR_MEMORY;
404 /* Parse out the header & info */
406 if (xp_HUGE_STRLEN (raw_manifest) >= SZ)
408 /* almost certainly nonsense */
409 PORT_Free (met);
410 continue;
413 xp_HUGE_STRCPY (line, raw_manifest);
414 x_info = line;
416 while (*x_info && *x_info != ' ' && *x_info != '\t' && *x_info != ':')
417 x_info++;
419 if (*x_info) *x_info++ = 0;
421 while (*x_info == ' ' || *x_info == '\t')
422 x_info++;
424 /* metainfo (name, value) pair is now (line, x_info) */
426 met->header = PORT_Strdup (line);
427 met->info = PORT_Strdup (x_info);
429 if (type == jarTypeMF)
431 ADDITEM (jar->metainfo, jarTypeMeta,
432 /* pathname */ NULL, met, sizeof (JAR_Metainfo));
435 /* For SF files, this metadata may be the digests
436 of the MF file, still in the "met" structure. */
438 if (type == jarTypeSF)
440 if (!PORT_Strcasecmp (line, "MD5-Digest"))
441 sf_md5 = (char *) met->info;
443 if (!PORT_Strcasecmp (line, "SHA1-Digest") || !PORT_Strcasecmp (line, "SHA-Digest"))
444 sf_sha1 = (char *) met->info;
447 if (type != jarTypeMF)
449 PORT_Free (met->header);
450 if (type != jarTypeSF)
452 PORT_Free (met->info);
454 PORT_Free (met);
458 if (type == jarTypeSF && jar->globalmeta)
460 /* this is a SF file which may contain a digest of the manifest.mf's
461 global metainfo. */
463 int match = 0;
464 JAR_Digest *glob = jar->globalmeta;
466 if (sf_md5)
468 unsigned int md5_length;
469 unsigned char *md5_digest;
471 md5_digest = ATOB_AsciiToData (sf_md5, &md5_length);
472 PORT_Assert( md5_length == MD5_LENGTH );
474 if (md5_length != MD5_LENGTH)
475 return JAR_ERR_CORRUPT;
477 match = PORT_Memcmp (md5_digest, glob->md5, MD5_LENGTH);
480 if (sf_sha1 && match == 0)
482 unsigned int sha1_length;
483 unsigned char *sha1_digest;
485 sha1_digest = ATOB_AsciiToData (sf_sha1, &sha1_length);
486 PORT_Assert( sha1_length == SHA1_LENGTH );
488 if (sha1_length != SHA1_LENGTH)
489 return JAR_ERR_CORRUPT;
491 match = PORT_Memcmp (sha1_digest, glob->sha1, SHA1_LENGTH);
494 if (match != 0)
496 /* global digest doesn't match, SF file therefore invalid */
497 jar->valid = JAR_ERR_METADATA;
498 return JAR_ERR_METADATA;
502 /* done with top section of global data */
505 while (raw_len)
507 *x_md5 = 0;
508 *x_sha = 0;
509 *x_name = 0;
512 /* If this is a manifest file, attempt to get a digest of the following section,
513 without damaging it. This digest will be saved later. */
515 if (type == jarTypeMF)
517 char ZHUGEP *sec;
518 long sec_len = raw_len;
520 if (!*raw_manifest || *raw_manifest == '\n')
522 /* skip the blank line */
523 sec = jar_eat_line (1, PR_FALSE, raw_manifest, &sec_len);
525 else
526 sec = raw_manifest;
528 if (!xp_HUGE_STRNCASECMP (sec, "Name:", 5))
530 if (type == jarTypeMF)
531 mfdig = jar_digest_section (sec, sec_len);
532 else
533 mfdig = NULL;
538 while (raw_len)
540 raw_manifest = jar_eat_line (1, PR_TRUE, raw_manifest, &raw_len);
541 if (!*raw_manifest) break; /* blank line, done with this entry */
543 if (xp_HUGE_STRLEN (raw_manifest) >= SZ)
545 /* almost certainly nonsense */
546 continue;
550 /* Parse out the name/value pair */
552 xp_HUGE_STRCPY (line, raw_manifest);
553 x_info = line;
555 while (*x_info && *x_info != ' ' && *x_info != '\t' && *x_info != ':')
556 x_info++;
558 if (*x_info) *x_info++ = 0;
560 while (*x_info == ' ' || *x_info == '\t')
561 x_info++;
564 if (!PORT_Strcasecmp (line, "Name"))
565 PORT_Strcpy (x_name, x_info);
567 else if (!PORT_Strcasecmp (line, "MD5-Digest"))
568 PORT_Strcpy (x_md5, x_info);
570 else if (!PORT_Strcasecmp (line, "SHA1-Digest")
571 || !PORT_Strcasecmp (line, "SHA-Digest"))
573 PORT_Strcpy (x_sha, x_info);
576 /* Algorithm list is meta info we don't care about; keeping it out
577 of metadata saves significant space for large jar files */
579 else if (!PORT_Strcasecmp (line, "Digest-Algorithms")
580 || !PORT_Strcasecmp (line, "Hash-Algorithms"))
582 continue;
585 /* Meta info is only collected for the manifest.mf file,
586 since the JAR_get_metainfo call does not support identity */
588 else if (type == jarTypeMF)
590 JAR_Metainfo *met;
592 /* this is meta-data */
594 met = (JAR_Metainfo*)PORT_ZAlloc (sizeof (JAR_Metainfo));
596 if (met == NULL)
597 return JAR_ERR_MEMORY;
599 /* metainfo (name, value) pair is now (line, x_info) */
601 if ((met->header = PORT_Strdup (line)) == NULL)
603 PORT_Free (met);
604 return JAR_ERR_MEMORY;
607 if ((met->info = PORT_Strdup (x_info)) == NULL)
609 PORT_Free (met->header);
610 PORT_Free (met);
611 return JAR_ERR_MEMORY;
614 ADDITEM (jar->metainfo, jarTypeMeta,
615 x_name, met, sizeof (JAR_Metainfo));
619 if(!x_name || !*x_name) {
620 /* Whatever that was, it wasn't an entry, because we didn't get a name.
621 * We don't really have anything, so don't record this. */
622 continue;
625 dig = (JAR_Digest*)PORT_ZAlloc (sizeof (JAR_Digest));
626 if (dig == NULL)
627 return JAR_ERR_MEMORY;
629 if (*x_md5 )
631 unsigned int binary_length;
632 unsigned char *binary_digest;
634 binary_digest = ATOB_AsciiToData (x_md5, &binary_length);
635 PORT_Assert( binary_length == MD5_LENGTH );
637 if (binary_length != MD5_LENGTH)
639 PORT_Free (dig);
640 return JAR_ERR_CORRUPT;
643 memcpy (dig->md5, binary_digest, MD5_LENGTH);
644 dig->md5_status = jarHashPresent;
647 if (*x_sha )
649 unsigned int binary_length;
650 unsigned char *binary_digest;
652 binary_digest = ATOB_AsciiToData (x_sha, &binary_length);
653 PORT_Assert( binary_length == SHA1_LENGTH );
655 if (binary_length != SHA1_LENGTH)
657 PORT_Free (dig);
658 return JAR_ERR_CORRUPT;
661 memcpy (dig->sha1, binary_digest, SHA1_LENGTH);
662 dig->sha1_status = jarHashPresent;
665 PORT_Assert( type == jarTypeMF || type == jarTypeSF );
668 if (type == jarTypeMF)
670 ADDITEM (jar->hashes, jarTypeMF, x_name, dig, sizeof (JAR_Digest));
672 else if (type == jarTypeSF)
674 ADDITEM (signer->sf, jarTypeSF, x_name, dig, sizeof (JAR_Digest));
676 else
678 PORT_Free (dig);
679 return JAR_ERR_ORDER;
682 /* we're placing these calculated digests of manifest.mf
683 sections in a list where they can subsequently be forgotten */
685 if (type == jarTypeMF && mfdig)
687 ADDITEM (jar->manifest, jarTypeSect,
688 x_name, mfdig, sizeof (JAR_Digest));
690 mfdig = NULL;
694 /* Retrieve our saved SHA1 digest from saved copy and check digests.
695 This is just comparing the digest of the MF section as indicated in
696 the SF file with the one we remembered from parsing the MF file */
698 if (type == jarTypeSF)
700 if ((status = jar_internal_digest (jar, path, x_name, dig)) < 0)
701 return status;
705 return 0;
708 static int jar_internal_digest
709 (JAR *jar, const char *path, char *x_name, JAR_Digest *dig)
711 int cv;
712 int status;
714 JAR_Digest *savdig;
716 savdig = jar_get_mf_digest (jar, x_name);
718 if (savdig == NULL)
720 /* no .mf digest for this pathname */
721 status = jar_signal (JAR_ERR_ENTRY, jar, path, x_name);
722 if (status < 0)
723 return 0; /* was continue; */
724 else
725 return status;
728 /* check for md5 consistency */
729 if (dig->md5_status)
731 cv = PORT_Memcmp (savdig->md5, dig->md5, MD5_LENGTH);
732 /* md5 hash of .mf file is not what expected */
733 if (cv)
735 status = jar_signal (JAR_ERR_HASH, jar, path, x_name);
737 /* bad hash, man */
739 dig->md5_status = jarHashBad;
740 savdig->md5_status = jarHashBad;
742 if (status < 0)
743 return 0; /* was continue; */
744 else
745 return status;
749 /* check for sha1 consistency */
750 if (dig->sha1_status)
752 cv = PORT_Memcmp (savdig->sha1, dig->sha1, SHA1_LENGTH);
753 /* sha1 hash of .mf file is not what expected */
754 if (cv)
756 status = jar_signal (JAR_ERR_HASH, jar, path, x_name);
758 /* bad hash, man */
760 dig->sha1_status = jarHashBad;
761 savdig->sha1_status = jarHashBad;
763 if (status < 0)
764 return 0; /* was continue; */
765 else
766 return status;
769 return 0;
772 #ifdef DEBUG
774 * j a r _ i n s a n i t y _ c h e c k
776 * Check for illegal characters (or possibly so)
777 * in the manifest files, to detect potential memory
778 * corruption by our neighbors. Debug only, since
779 * not I18N safe.
783 static int jar_insanity_check (char ZHUGEP *data, long length)
785 int c;
786 long off;
788 for (off = 0; off < length; off++)
790 c = data [off];
792 if (c == '\n' || c == '\r' || (c >= ' ' && c <= 128))
793 continue;
795 return JAR_ERR_CORRUPT;
798 return 0;
800 #endif
803 * j a r _ p a r s e _ d i g i t a l _ s i g n a t u r e
805 * Parse an RSA or DSA (or perhaps other) digital signature.
806 * Right now everything is PKCS7.
810 static int jar_parse_digital_signature
811 (char *raw_manifest, JAR_Signer *signer, long length, JAR *jar)
813 return jar_validate_pkcs7 (jar, signer, raw_manifest, length);
817 * j a r _ a d d _ c e r t
819 * Add information for the given certificate
820 * (or whatever) to the JAR linked list. A pointer
821 * is passed for some relevant reference, say
822 * for example the original certificate.
826 static int jar_add_cert
827 (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert)
829 JAR_Cert *fing;
830 unsigned char *keyData;
832 if (cert == NULL)
833 return JAR_ERR_ORDER;
835 fing = (JAR_Cert*)PORT_ZAlloc (sizeof (JAR_Cert));
837 if (fing == NULL)
838 goto loser;
840 fing->cert = CERT_DupCertificate (cert);
842 /* get the certkey */
844 fing->length = cert->derIssuer.len + 2 + cert->serialNumber.len;
846 keyData = (unsigned char *) PORT_ZAlloc (fing->length);
847 fing->key = keyData;
849 if (fing->key == NULL)
850 goto loser;
851 keyData[0] = ((cert->derIssuer.len) >> 8) & 0xff;
852 keyData[1] = ((cert->derIssuer.len) & 0xff);
853 PORT_Memcpy (&keyData[2], cert->derIssuer.data, cert->derIssuer.len);
854 PORT_Memcpy (&keyData[2+cert->derIssuer.len], cert->serialNumber.data,
855 cert->serialNumber.len);
857 ADDITEM (signer->certs, type,
858 /* pathname */ NULL, fing, sizeof (JAR_Cert));
860 return 0;
862 loser:
864 if (fing)
866 if (fing->cert)
867 CERT_DestroyCertificate (fing->cert);
869 PORT_Free (fing);
872 return JAR_ERR_MEMORY;
876 * e a t _ l i n e
878 * Consume an ascii line from the top of a file kept
879 * in memory. This destroys the file in place. This function
880 * handles PC, Mac, and Unix style text files.
884 static char ZHUGEP *jar_eat_line
885 (int lines, int eating, char ZHUGEP *data, long *len)
887 char ZHUGEP *ret;
889 ret = data;
890 if (!*len) return ret;
892 /* Eat the requisite number of lines, if any;
893 prior to terminating the current line with a 0. */
895 for (/* yip */ ; lines; lines--)
897 while (*data && *data != '\n')
898 data++;
900 /* After the CR, ok to eat one LF */
902 if (*data == '\n')
903 data++;
905 /* If there are zeros, we put them there */
907 while (*data == 0 && data - ret < *len)
908 data++;
911 *len -= data - ret;
912 ret = data;
914 if (eating)
916 /* Terminate this line with a 0 */
918 while (*data && *data != '\n' && *data != '\r')
919 data++;
921 /* In any case we are allowed to eat CR */
923 if (*data == '\r')
924 *data++ = 0;
926 /* After the CR, ok to eat one LF */
928 if (*data == '\n')
929 *data++ = 0;
932 return ret;
936 * j a r _ d i g e s t _ s e c t i o n
938 * Return the digests of the next section of the manifest file.
939 * Does not damage the manifest file, unlike parse_manifest.
943 static JAR_Digest *jar_digest_section
944 (char ZHUGEP *manifest, long length)
946 long global_len;
947 char ZHUGEP *global_end;
949 global_end = manifest;
950 global_len = length;
952 while (global_len)
954 global_end = jar_eat_line (1, PR_FALSE, global_end, &global_len);
955 if (*global_end == 0 || *global_end == '\n')
956 break;
959 return JAR_calculate_digest (manifest, global_end - manifest);
963 * J A R _ v e r i f y _ d i g e s t
965 * Verifies that a precalculated digest matches the
966 * expected value in the manifest.
970 int PR_CALLBACK JAR_verify_digest
971 (JAR *jar, const char *name, JAR_Digest *dig)
973 JAR_Item *it;
975 JAR_Digest *shindig;
977 ZZLink *link;
978 ZZList *list;
980 int result1, result2;
982 list = jar->hashes;
984 result1 = result2 = 0;
986 if (jar->valid < 0)
988 /* signature not valid */
989 return JAR_ERR_SIG;
992 if (ZZ_ListEmpty (list))
994 /* empty list */
995 return JAR_ERR_PNF;
998 for (link = ZZ_ListHead (list);
999 !ZZ_ListIterDone (list, link);
1000 link = link->next)
1002 it = link->thing;
1003 if (it->type == jarTypeMF
1004 && it->pathname && !PORT_Strcmp (it->pathname, name))
1006 shindig = (JAR_Digest *) it->data;
1008 if (shindig->md5_status)
1010 if (shindig->md5_status == jarHashBad)
1011 return JAR_ERR_HASH;
1012 else
1013 result1 = memcmp (dig->md5, shindig->md5, MD5_LENGTH);
1016 if (shindig->sha1_status)
1018 if (shindig->sha1_status == jarHashBad)
1019 return JAR_ERR_HASH;
1020 else
1021 result2 = memcmp (dig->sha1, shindig->sha1, SHA1_LENGTH);
1024 return (result1 == 0 && result2 == 0) ? 0 : JAR_ERR_HASH;
1028 return JAR_ERR_PNF;
1032 * J A R _ c e r t _ a t t r i b u t e
1034 * Return the named certificate attribute from the
1035 * certificate specified by the given key.
1039 int PR_CALLBACK JAR_cert_attribute
1040 (JAR *jar, jarCert attrib, long keylen, void *key,
1041 void **result, unsigned long *length)
1043 int status = 0;
1044 char *ret = NULL;
1046 CERTCertificate *cert;
1048 CERTCertDBHandle *certdb;
1050 JAR_Digest *dig;
1051 SECItem hexme;
1053 *length = 0;
1055 if (attrib == 0 || key == 0)
1056 return JAR_ERR_GENERAL;
1058 if (attrib == jarCertJavaHack)
1060 cert = (CERTCertificate *) NULL;
1061 certdb = JAR_open_database();
1063 if (certdb)
1065 cert = CERT_FindCertByNickname (certdb, key);
1067 if (cert)
1069 *length = cert->certKey.len;
1071 *result = (void *) PORT_ZAlloc (*length);
1073 if (*result)
1074 PORT_Memcpy (*result, cert->certKey.data, *length);
1075 else
1077 JAR_close_database (certdb);
1078 return JAR_ERR_MEMORY;
1081 JAR_close_database (certdb);
1084 return cert ? 0 : JAR_ERR_GENERAL;
1087 if (jar && jar->pkcs7 == 0)
1088 return JAR_ERR_GENERAL;
1090 cert = jar_get_certificate (jar, keylen, key, &status);
1092 if (cert == NULL || status < 0)
1093 return JAR_ERR_GENERAL;
1095 #define SEP " <br> "
1096 #define SEPLEN (PORT_Strlen(SEP))
1098 switch (attrib)
1100 case jarCertCompany:
1102 ret = cert->subjectName;
1104 /* This is pretty ugly looking but only used
1105 here for this one purpose. */
1107 if (ret)
1109 int retlen = 0;
1111 char *cer_ou1, *cer_ou2, *cer_ou3;
1112 char *cer_cn, *cer_e, *cer_o, *cer_l;
1114 cer_cn = CERT_GetCommonName (&cert->subject);
1115 cer_e = CERT_GetCertEmailAddress (&cert->subject);
1116 cer_ou3 = jar_cert_element (ret, "OU=", 3);
1117 cer_ou2 = jar_cert_element (ret, "OU=", 2);
1118 cer_ou1 = jar_cert_element (ret, "OU=", 1);
1119 cer_o = CERT_GetOrgName (&cert->subject);
1120 cer_l = CERT_GetCountryName (&cert->subject);
1122 if (cer_cn) retlen += SEPLEN + PORT_Strlen (cer_cn);
1123 if (cer_e) retlen += SEPLEN + PORT_Strlen (cer_e);
1124 if (cer_ou1) retlen += SEPLEN + PORT_Strlen (cer_ou1);
1125 if (cer_ou2) retlen += SEPLEN + PORT_Strlen (cer_ou2);
1126 if (cer_ou3) retlen += SEPLEN + PORT_Strlen (cer_ou3);
1127 if (cer_o) retlen += SEPLEN + PORT_Strlen (cer_o);
1128 if (cer_l) retlen += SEPLEN + PORT_Strlen (cer_l);
1130 ret = (char *) PORT_ZAlloc (1 + retlen);
1132 if (cer_cn) { PORT_Strcpy (ret, cer_cn); PORT_Strcat (ret, SEP); }
1133 if (cer_e) { PORT_Strcat (ret, cer_e); PORT_Strcat (ret, SEP); }
1134 if (cer_ou1) { PORT_Strcat (ret, cer_ou1); PORT_Strcat (ret, SEP); }
1135 if (cer_ou2) { PORT_Strcat (ret, cer_ou2); PORT_Strcat (ret, SEP); }
1136 if (cer_ou3) { PORT_Strcat (ret, cer_ou3); PORT_Strcat (ret, SEP); }
1137 if (cer_o) { PORT_Strcat (ret, cer_o); PORT_Strcat (ret, SEP); }
1138 if (cer_l) PORT_Strcat (ret, cer_l);
1140 /* return here to avoid unsightly memory leak */
1142 *result = ret;
1143 *length = PORT_Strlen (ret);
1145 return 0;
1147 break;
1149 case jarCertCA:
1151 ret = cert->issuerName;
1153 if (ret)
1155 int retlen = 0;
1157 char *cer_ou1, *cer_ou2, *cer_ou3;
1158 char *cer_cn, *cer_e, *cer_o, *cer_l;
1160 /* This is pretty ugly looking but only used
1161 here for this one purpose. */
1163 cer_cn = CERT_GetCommonName (&cert->issuer);
1164 cer_e = CERT_GetCertEmailAddress (&cert->issuer);
1165 cer_ou3 = jar_cert_element (ret, "OU=", 3);
1166 cer_ou2 = jar_cert_element (ret, "OU=", 2);
1167 cer_ou1 = jar_cert_element (ret, "OU=", 1);
1168 cer_o = CERT_GetOrgName (&cert->issuer);
1169 cer_l = CERT_GetCountryName (&cert->issuer);
1171 if (cer_cn) retlen += SEPLEN + PORT_Strlen (cer_cn);
1172 if (cer_e) retlen += SEPLEN + PORT_Strlen (cer_e);
1173 if (cer_ou1) retlen += SEPLEN + PORT_Strlen (cer_ou1);
1174 if (cer_ou2) retlen += SEPLEN + PORT_Strlen (cer_ou2);
1175 if (cer_ou3) retlen += SEPLEN + PORT_Strlen (cer_ou3);
1176 if (cer_o) retlen += SEPLEN + PORT_Strlen (cer_o);
1177 if (cer_l) retlen += SEPLEN + PORT_Strlen (cer_l);
1179 ret = (char *) PORT_ZAlloc (1 + retlen);
1181 if (cer_cn) { PORT_Strcpy (ret, cer_cn); PORT_Strcat (ret, SEP); }
1182 if (cer_e) { PORT_Strcat (ret, cer_e); PORT_Strcat (ret, SEP); }
1183 if (cer_ou1) { PORT_Strcat (ret, cer_ou1); PORT_Strcat (ret, SEP); }
1184 if (cer_ou2) { PORT_Strcat (ret, cer_ou2); PORT_Strcat (ret, SEP); }
1185 if (cer_ou3) { PORT_Strcat (ret, cer_ou3); PORT_Strcat (ret, SEP); }
1186 if (cer_o) { PORT_Strcat (ret, cer_o); PORT_Strcat (ret, SEP); }
1187 if (cer_l) PORT_Strcat (ret, cer_l);
1189 /* return here to avoid unsightly memory leak */
1191 *result = ret;
1192 *length = PORT_Strlen (ret);
1194 return 0;
1197 break;
1199 case jarCertSerial:
1201 ret = CERT_Hexify (&cert->serialNumber, 1);
1202 break;
1204 case jarCertExpires:
1206 ret = DER_UTCDayToAscii (&cert->validity.notAfter);
1207 break;
1209 case jarCertNickname:
1211 ret = jar_choose_nickname (cert);
1212 break;
1214 case jarCertFinger:
1216 dig = JAR_calculate_digest
1217 ((char *) cert->derCert.data, cert->derCert.len);
1219 if (dig)
1221 hexme.len = sizeof (dig->md5);
1222 hexme.data = dig->md5;
1223 ret = CERT_Hexify (&hexme, 1);
1225 break;
1227 default:
1229 return JAR_ERR_GENERAL;
1232 *result = ret ? PORT_Strdup (ret) : NULL;
1233 *length = ret ? PORT_Strlen (ret) : 0;
1235 return 0;
1239 * j a r _ c e r t _ e l e m e n t
1241 * Retrieve an element from an x400ish ascii
1242 * designator, in a hackish sort of way. The right
1243 * thing would probably be to sort AVATags.
1247 static char *jar_cert_element (char *name, char *tag, int occ)
1249 if (name && tag)
1251 char *s;
1252 int found = 0;
1254 while (occ--)
1256 if (PORT_Strstr (name, tag))
1258 name = PORT_Strstr (name, tag) + PORT_Strlen (tag);
1259 found = 1;
1261 else
1263 name = PORT_Strstr (name, "=");
1264 if (name == NULL) return NULL;
1265 found = 0;
1269 if (!found) return NULL;
1271 /* must mangle only the copy */
1272 name = PORT_Strdup (name);
1274 /* advance to next equal */
1275 for (s = name; *s && *s != '='; s++)
1276 /* yip */ ;
1278 /* back up to previous comma */
1279 while (s > name && *s != ',') s--;
1281 /* zap the whitespace and return */
1282 *s = 0;
1285 return name;
1289 * j a r _ c h o o s e _ n i c k n a m e
1291 * Attempt to determine a suitable nickname for
1292 * a certificate with a computer-generated "tmpcertxxx"
1293 * nickname. It needs to be something a user can
1294 * understand, so try a few things.
1298 static char *jar_choose_nickname (CERTCertificate *cert)
1300 char *cert_cn;
1301 char *cert_o;
1302 char *cert_cn_o;
1304 int cn_o_length;
1306 /* is the existing name ok */
1308 if (cert->nickname && PORT_Strncmp (cert->nickname, "tmpcert", 7))
1309 return PORT_Strdup (cert->nickname);
1311 /* we have an ugly name here people */
1313 /* Try the CN */
1314 cert_cn = CERT_GetCommonName (&cert->subject);
1316 if (cert_cn)
1318 /* check for duplicate nickname */
1320 if (CERT_FindCertByNickname (CERT_GetDefaultCertDB(), cert_cn) == NULL)
1321 return cert_cn;
1323 /* Try the CN plus O */
1324 cert_o = CERT_GetOrgName (&cert->subject);
1326 cn_o_length = PORT_Strlen (cert_cn) + 3 + PORT_Strlen (cert_o) + 20;
1327 cert_cn_o = (char*)PORT_ZAlloc (cn_o_length);
1329 PR_snprintf (cert_cn_o, cn_o_length,
1330 "%s's %s Certificate", cert_cn, cert_o);
1332 if (CERT_FindCertByNickname (CERT_GetDefaultCertDB(), cert_cn_o) == NULL)
1334 PORT_Free (cert_cn_o);
1335 return cert_cn;
1337 PORT_Free (cert_cn_o);
1340 /* If all that failed, use the ugly nickname */
1341 return cert->nickname ? PORT_Strdup (cert->nickname) : NULL;
1345 * J A R _ c e r t _ h t m l
1347 * Return an HTML representation of the certificate
1348 * designated by the given fingerprint, in specified style.
1350 * JAR is optional, but supply it if you can in order
1351 * to optimize.
1355 char *JAR_cert_html
1356 (JAR *jar, int style, long keylen, void *key, int *result)
1358 CERTCertificate *cert;
1360 *result = -1;
1362 if (style != 0)
1363 return NULL;
1365 cert = jar_get_certificate (jar, keylen, key, result);
1367 if (cert == NULL || *result < 0)
1368 return NULL;
1370 *result = -1;
1372 return NULL;
1376 * J A R _ s t a s h _ c e r t
1378 * Stash the certificate pointed to by this
1379 * fingerprint, in persistent storage somewhere.
1383 extern int PR_CALLBACK JAR_stash_cert
1384 (JAR *jar, long keylen, void *key)
1386 int result = 0;
1388 char *nickname;
1389 CERTCertTrust trust;
1391 CERTCertDBHandle *certdb;
1392 CERTCertificate *cert, *newcert;
1394 cert = jar_get_certificate (jar, keylen, key, &result);
1396 if (result < 0)
1397 return result;
1399 if (cert == NULL)
1400 return JAR_ERR_GENERAL;
1402 if ((certdb = JAR_open_database()) == NULL)
1403 return JAR_ERR_GENERAL;
1405 /* Attempt to give a name to the newish certificate */
1406 nickname = jar_choose_nickname (cert);
1408 newcert = CERT_FindCertByNickname (certdb, nickname);
1410 if (newcert && newcert->isperm)
1412 /* already in permanant database */
1413 JAR_close_database (certdb);
1414 return 0;
1417 if (newcert) cert = newcert;
1419 /* FIX, since FindCert returns a bogus dbhandle
1420 set it ourselves */
1422 cert->dbhandle = certdb;
1424 if (nickname != NULL)
1426 PORT_Memset ((void *) &trust, 0, sizeof(trust));
1428 if (CERT_AddTempCertToPerm (cert, nickname, &trust) != SECSuccess)
1430 /* XXX might want to call PORT_GetError here */
1431 result = JAR_ERR_GENERAL;
1435 JAR_close_database (certdb);
1437 return result;
1441 * J A R _ f e t c h _ c e r t
1443 * Given an opaque identifier of a certificate,
1444 * return the full certificate.
1446 * The new function, which retrieves by key.
1450 void *JAR_fetch_cert (long length, void *key)
1452 CERTIssuerAndSN issuerSN;
1453 CERTCertificate *cert = NULL;
1455 CERTCertDBHandle *certdb;
1457 certdb = JAR_open_database();
1459 if (certdb)
1461 unsigned char *keyData = (unsigned char *)key;
1462 issuerSN.derIssuer.len = (keyData[0] << 8) + keyData[0];
1463 issuerSN.derIssuer.data = &keyData[2];
1464 issuerSN.serialNumber.len = length - (2 + issuerSN.derIssuer.len);
1465 issuerSN.serialNumber.data = &keyData[2+issuerSN.derIssuer.len];
1467 cert = CERT_FindCertByIssuerAndSN (certdb, &issuerSN);
1469 JAR_close_database (certdb);
1472 return (void *) cert;
1476 * j a r _ g e t _ m f _ d i g e s t
1478 * Retrieve a corresponding saved digest over a section
1479 * of the main manifest file.
1483 static JAR_Digest *jar_get_mf_digest (JAR *jar, char *pathname)
1485 JAR_Item *it;
1487 JAR_Digest *dig;
1489 ZZLink *link;
1490 ZZList *list;
1492 list = jar->manifest;
1494 if (ZZ_ListEmpty (list))
1495 return NULL;
1497 for (link = ZZ_ListHead (list);
1498 !ZZ_ListIterDone (list, link);
1499 link = link->next)
1501 it = link->thing;
1502 if (it->type == jarTypeSect
1503 && it->pathname && !PORT_Strcmp (it->pathname, pathname))
1505 dig = (JAR_Digest *) it->data;
1506 return dig;
1510 return NULL;
1514 * j a r _ b a s e n a m e
1516 * Return the basename -- leading components of path stripped off,
1517 * extension ripped off -- of a path.
1521 static char *jar_basename (const char *path)
1523 char *pith, *e, *basename, *ext;
1525 if (path == NULL)
1526 return PORT_Strdup ("");
1528 pith = PORT_Strdup (path);
1530 basename = pith;
1532 while (1)
1534 for (e = basename; *e && *e != '/' && *e != '\\'; e++)
1535 /* yip */ ;
1536 if (*e)
1537 basename = ++e;
1538 else
1539 break;
1542 if ((ext = PORT_Strrchr (basename, '.')) != NULL)
1543 *ext = 0;
1545 /* We already have the space allocated */
1546 PORT_Strcpy (pith, basename);
1548 return pith;
1552 * + + + + + + + + + + + + + + +
1554 * CRYPTO ROUTINES FOR JAR
1556 * The following functions are the cryptographic
1557 * interface to PKCS7 for Jarnatures.
1559 * + + + + + + + + + + + + + + +
1564 * j a r _ c a t c h _ b y t e s
1566 * In the event signatures contain enveloped data, it will show up here.
1567 * But note that the lib/pkcs7 routines aren't ready for it.
1571 static void jar_catch_bytes
1572 (void *arg, const char *buf, unsigned long len)
1574 /* Actually this should never be called, since there is
1575 presumably no data in the signature itself. */
1579 * j a r _ v a l i d a t e _ p k c s 7
1581 * Validate (and decode, if necessary) a binary pkcs7
1582 * signature in DER format.
1586 static int jar_validate_pkcs7
1587 (JAR *jar, JAR_Signer *signer, char *data, long length)
1590 SEC_PKCS7ContentInfo *cinfo = NULL;
1591 SEC_PKCS7DecoderContext *dcx;
1592 PRBool goodSig;
1593 int status = 0;
1594 SECItem detdig;
1596 PORT_Assert( jar != NULL && signer != NULL );
1598 if (jar == NULL || signer == NULL)
1599 return JAR_ERR_ORDER;
1601 signer->valid = JAR_ERR_SIG;
1603 /* We need a context if we can get one */
1605 #ifdef MOZILLA_CLIENT_OLD
1606 if (jar->mw == NULL) {
1607 JAR_set_context (jar, NULL);
1609 #endif
1612 dcx = SEC_PKCS7DecoderStart
1613 (jar_catch_bytes, NULL /*cb_arg*/, NULL /*getpassword*/, jar->mw,
1614 NULL, NULL, NULL);
1616 if (dcx == NULL)
1618 /* strange pkcs7 failure */
1619 return JAR_ERR_PK7;
1622 SEC_PKCS7DecoderUpdate (dcx, data, length);
1623 cinfo = SEC_PKCS7DecoderFinish (dcx);
1625 if (cinfo == NULL)
1627 /* strange pkcs7 failure */
1628 return JAR_ERR_PK7;
1631 if (SEC_PKCS7ContentIsEncrypted (cinfo))
1633 /* content was encrypted, fail */
1634 return JAR_ERR_PK7;
1637 if (SEC_PKCS7ContentIsSigned (cinfo) == PR_FALSE)
1639 /* content was not signed, fail */
1640 return JAR_ERR_PK7;
1643 PORT_SetError (0);
1645 /* use SHA1 only */
1647 detdig.len = SHA1_LENGTH;
1648 detdig.data = signer->digest->sha1;
1650 goodSig = SEC_PKCS7VerifyDetachedSignature(cinfo, certUsageObjectSigner,
1651 &detdig, HASH_AlgSHA1, PR_FALSE);
1652 jar_gather_signers (jar, signer, cinfo);
1653 if (goodSig == PR_TRUE)
1655 /* signature is valid */
1656 signer->valid = 0;
1658 else
1660 status = PORT_GetError();
1662 PORT_Assert( status < 0 );
1663 if (status >= 0) status = JAR_ERR_SIG;
1665 jar->valid = status;
1666 signer->valid = status;
1669 jar->pkcs7 = PR_TRUE;
1670 signer->pkcs7 = PR_TRUE;
1672 SEC_PKCS7DestroyContentInfo (cinfo);
1674 return status;
1678 * j a r _ g a t h e r _ s i g n e r s
1680 * Add the single signer of this signature to the
1681 * certificate linked list.
1685 static int jar_gather_signers
1686 (JAR *jar, JAR_Signer *signer, SEC_PKCS7ContentInfo *cinfo)
1688 int result;
1690 CERTCertificate *cert;
1691 CERTCertDBHandle *certdb;
1693 SEC_PKCS7SignedData *sdp;
1694 SEC_PKCS7SignerInfo **pksigners, *pksigner;
1696 sdp = cinfo->content.signedData;
1698 if (sdp == NULL)
1699 return JAR_ERR_PK7;
1701 pksigners = sdp->signerInfos;
1703 /* permit exactly one signer */
1705 if (pksigners == NULL || pksigners [0] == NULL || pksigners [1] != NULL)
1706 return JAR_ERR_PK7;
1708 pksigner = *pksigners;
1709 cert = pksigner->cert;
1711 if (cert == NULL)
1712 return JAR_ERR_PK7;
1714 certdb = JAR_open_database();
1716 if (certdb == NULL)
1717 return JAR_ERR_GENERAL;
1719 result = jar_add_cert (jar, signer, jarTypeSign, cert);
1721 JAR_close_database (certdb);
1723 return result;
1727 * j a r _ o p e n _ d a t a b a s e
1729 * Open the certificate database,
1730 * for use by JAR functions.
1734 CERTCertDBHandle *JAR_open_database (void)
1736 CERTCertDBHandle *certdb;
1738 certdb = CERT_GetDefaultCertDB();
1740 return certdb;
1744 * j a r _ c l o s e _ d a t a b a s e
1746 * Close the certificate database.
1747 * For use by JAR functions.
1751 int JAR_close_database (CERTCertDBHandle *certdb)
1753 return 0;
1757 * j a r _ g e t _ c e r t i f i c a t e
1759 * Return the certificate referenced
1760 * by a given fingerprint, or NULL if not found.
1761 * Error code is returned in result.
1765 static CERTCertificate *jar_get_certificate
1766 (JAR *jar, long keylen, void *key, int *result)
1768 int found = 0;
1770 JAR_Item *it;
1771 JAR_Cert *fing = NULL;
1773 JAR_Context *ctx;
1775 if (jar == NULL)
1777 void *cert;
1778 cert = JAR_fetch_cert (keylen, key);
1779 *result = (cert == NULL) ? JAR_ERR_GENERAL : 0;
1780 return (CERTCertificate *) cert;
1783 ctx = JAR_find (jar, NULL, jarTypeSign);
1785 while (JAR_find_next (ctx, &it) >= 0)
1787 fing = (JAR_Cert *) it->data;
1789 if (keylen != fing->length)
1790 continue;
1792 PORT_Assert( keylen < 0xFFFF );
1793 if (!PORT_Memcmp (fing->key, key, keylen))
1795 found = 1;
1796 break;
1800 JAR_find_end (ctx);
1802 if (found == 0)
1804 *result = JAR_ERR_GENERAL;
1805 return NULL;
1808 PORT_Assert(fing != NULL);
1809 *result = 0;
1810 return fing->cert;
1814 * j a r _ s i g n a l
1816 * Nonfatal errors come here to callback Java.
1820 static int jar_signal
1821 (int status, JAR *jar, const char *metafile, char *pathname)
1823 char *errstring;
1825 errstring = JAR_get_error (status);
1827 if (jar->signal)
1829 (*jar->signal) (status, jar, metafile, pathname, errstring);
1830 return 0;
1833 return status;
1837 * j a r _ a p p e n d
1839 * Tack on an element to one of a JAR's linked
1840 * lists, with rudimentary error handling.
1844 int jar_append (ZZList *list, int type,
1845 char *pathname, void *data, size_t size)
1847 JAR_Item *it;
1848 ZZLink *entity;
1850 it = (JAR_Item*)PORT_ZAlloc (sizeof (JAR_Item));
1852 if (it == NULL)
1853 goto loser;
1855 if (pathname)
1857 it->pathname = PORT_Strdup (pathname);
1858 if (it->pathname == NULL)
1859 goto loser;
1862 it->type = (jarType)type;
1863 it->data = (unsigned char *) data;
1864 it->size = size;
1866 entity = ZZ_NewLink (it);
1868 if (entity)
1870 ZZ_AppendLink (list, entity);
1871 return 0;
1874 loser:
1876 if (it)
1878 if (it->pathname) PORT_Free (it->pathname);
1879 PORT_Free (it);
1882 return JAR_ERR_MEMORY;