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
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.
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 ***** */
41 * Routines common to signing and validating.
48 static void jar_destroy_list (ZZList
*list
);
50 static int jar_find_first_cert
51 (JAR_Signer
*signer
, int type
, JAR_Item
**it
);
56 * Create a new instantiation of a manifest representation.
57 * Use this as a token to any calls to this API.
65 if ((jar
= (JAR
*)PORT_ZAlloc (sizeof (JAR
))) == NULL
)
68 if ((jar
->manifest
= ZZ_NewList()) == NULL
)
71 if ((jar
->hashes
= ZZ_NewList()) == NULL
)
74 if ((jar
->phy
= ZZ_NewList()) == NULL
)
77 if ((jar
->metainfo
= ZZ_NewList()) == NULL
)
80 if ((jar
->signers
= ZZ_NewList()) == NULL
)
90 ZZ_DestroyList (jar
->manifest
);
93 ZZ_DestroyList (jar
->hashes
);
96 ZZ_DestroyList (jar
->phy
);
99 ZZ_DestroyList (jar
->metainfo
);
102 ZZ_DestroyList (jar
->signers
);
111 * J A R _ d e s t r o y
117 void PR_CALLBACK
JAR_destroy (JAR
*jar
)
119 PORT_Assert( jar
!= NULL
);
124 if (jar
->fp
) JAR_FCLOSE ((PRFileDesc
*)jar
->fp
);
126 if (jar
->url
) PORT_Free (jar
->url
);
127 if (jar
->filename
) PORT_Free (jar
->filename
);
129 /* Free the linked list elements */
131 jar_destroy_list (jar
->manifest
);
132 ZZ_DestroyList (jar
->manifest
);
134 jar_destroy_list (jar
->hashes
);
135 ZZ_DestroyList (jar
->hashes
);
137 jar_destroy_list (jar
->phy
);
138 ZZ_DestroyList (jar
->phy
);
140 jar_destroy_list (jar
->metainfo
);
141 ZZ_DestroyList (jar
->metainfo
);
143 jar_destroy_list (jar
->signers
);
144 ZZ_DestroyList (jar
->signers
);
149 static void jar_destroy_list (ZZList
*list
)
151 ZZLink
*link
, *oldlink
;
161 if (list
&& !ZZ_ListEmpty (list
))
163 link
= ZZ_ListHead (list
);
165 while (!ZZ_ListIterDone (list
, link
))
170 if (it
->pathname
) PORT_Free (it
->pathname
);
176 met
= (JAR_Metainfo
*) it
->data
;
179 if (met
->header
) PORT_Free (met
->header
);
180 if (met
->info
) PORT_Free (met
->info
);
187 phy
= (JAR_Physical
*) it
->data
;
194 fing
= (JAR_Cert
*) it
->data
;
198 CERT_DestroyCertificate (fing
->cert
);
200 PORT_Free (fing
->key
);
209 dig
= (JAR_Digest
*) it
->data
;
218 signer
= (JAR_Signer
*) it
->data
;
221 JAR_destroy_signer (signer
);
227 /* PORT_Assert( 1 != 2 ); */
238 ZZ_DestroyLink (oldlink
);
244 * J A R _ g e t _ m e t a i n f o
246 * Retrieve meta information from the manifest file.
247 * It doesn't matter whether it's from .MF or .SF, does it?
252 (JAR
*jar
, char *name
, char *header
, void **info
, unsigned long *length
)
261 PORT_Assert( jar
!= NULL
&& header
!= NULL
);
263 if (jar
== NULL
|| header
== NULL
)
266 list
= jar
->metainfo
;
268 if (ZZ_ListEmpty (list
))
271 for (link
= ZZ_ListHead (list
);
272 !ZZ_ListIterDone (list
, link
);
276 if (it
->type
== jarTypeMeta
)
278 if ((name
&& !it
->pathname
) || (!name
&& it
->pathname
))
281 if (name
&& it
->pathname
&& strcmp (it
->pathname
, name
))
284 met
= (JAR_Metainfo
*) it
->data
;
286 if (!PORT_Strcasecmp (met
->header
, header
))
288 *info
= PORT_Strdup (met
->info
);
289 *length
= PORT_Strlen (met
->info
);
301 * Establish the search pattern for use
302 * by JAR_find_next, to traverse the filenames
303 * or certificates in the JAR structure.
305 * See jar.h for a description on how to use.
309 JAR_Context
*JAR_find (JAR
*jar
, char *pattern
, jarType type
)
313 PORT_Assert( jar
!= NULL
);
318 ctx
= (JAR_Context
*) PORT_ZAlloc (sizeof (JAR_Context
));
327 if ((ctx
->pattern
= PORT_Strdup (pattern
)) == NULL
)
338 case jarTypeMF
: ctx
->next
= ZZ_ListHead (jar
->hashes
);
342 case jarTypeSign
: ctx
->next
= NULL
;
343 ctx
->nextsign
= ZZ_ListHead (jar
->signers
);
346 case jarTypeSect
: ctx
->next
= ZZ_ListHead (jar
->manifest
);
349 case jarTypePhy
: ctx
->next
= ZZ_ListHead (jar
->phy
);
352 case jarTypeOwner
: if (jar
->signers
)
353 ctx
->next
= ZZ_ListHead (jar
->signers
);
358 case jarTypeMeta
: ctx
->next
= ZZ_ListHead (jar
->metainfo
);
361 default: PORT_Assert( 1 != 2);
369 * J A R _ f i n d _ e n d
371 * Destroy the find iterator context.
375 void JAR_find_end (JAR_Context
*ctx
)
377 PORT_Assert( ctx
!= NULL
);
382 PORT_Free (ctx
->pattern
);
388 * J A R _ f i n d _ n e x t
390 * Return the next item of the given type
391 * from one of the JAR linked lists.
395 int JAR_find_next (JAR_Context
*ctx
, JAR_Item
**it
)
402 JAR_Signer
*signer
= NULL
;
404 PORT_Assert( ctx
!= NULL
);
405 PORT_Assert( ctx
->jar
!= NULL
);
409 /* Internally, convert jarTypeSign to jarTypeSF, and return
410 the actual attached certificate later */
412 finding
= (ctx
->finding
== jarTypeSign
) ? jarTypeSF
: ctx
->finding
;
416 if (ZZ_ListIterDone (jar
->signers
, ctx
->nextsign
))
421 PORT_Assert (ctx
->nextsign
->thing
!= NULL
);
422 signer
= (JAR_Signer
*)ctx
->nextsign
->thing
->data
;
426 /* Find out which linked list to traverse. Then if
427 necessary, advance to the next linked list. */
433 case jarTypeSign
: /* not any more */
434 PORT_Assert( finding
!= jarTypeSign
);
435 list
= signer
->certs
;
438 case jarTypeSect
: list
= jar
->manifest
;
441 case jarTypePhy
: list
= jar
->phy
;
444 case jarTypeSF
: /* signer, not jar */
445 PORT_Assert( signer
!= NULL
);
449 case jarTypeMF
: list
= jar
->hashes
;
452 case jarTypeOwner
: list
= jar
->signers
;
455 case jarTypeMeta
: list
= jar
->metainfo
;
458 default: PORT_Assert( 1 != 2 );
468 /* When looping over lists of lists, advance
469 to the next signer. This is done when multiple
470 signers are possible. */
472 if (ZZ_ListIterDone (list
, ctx
->next
))
474 if (ctx
->nextsign
&& jar
->signers
)
476 ctx
->nextsign
= ctx
->nextsign
->next
;
477 if (!ZZ_ListIterDone (jar
->signers
, ctx
->nextsign
))
479 PORT_Assert (ctx
->nextsign
->thing
!= NULL
);
481 signer
= (JAR_Signer
*)ctx
->nextsign
->thing
->data
;
482 PORT_Assert( signer
!= NULL
);
492 /* if the signer changed, still need to fill
493 in the "next" link */
495 if (ctx
->nextsign
&& ctx
->next
== NULL
)
501 ctx
->next
= ZZ_ListHead (signer
->sf
);
506 ctx
->next
= ZZ_ListHead (signer
->certs
);
511 PORT_Assert( ctx
->next
!= NULL
);
514 while (!ZZ_ListIterDone (list
, ctx
->next
))
516 *it
= ctx
->next
->thing
;
517 ctx
->next
= ctx
->next
->next
;
519 if (!*it
|| (*it
)->type
!= finding
)
522 if (ctx
->pattern
&& *ctx
->pattern
)
524 if (PORT_Strcmp ((*it
)->pathname
, ctx
->pattern
))
528 /* We have a valid match. If this is a jarTypeSign
529 return the certificate instead.. */
531 if (ctx
->finding
== jarTypeSign
)
535 /* just the first one for now */
536 if (jar_find_first_cert (signer
, jarTypeSign
, &itt
) >= 0)
551 static int jar_find_first_cert
552 (JAR_Signer
*signer
, int type
, JAR_Item
**it
)
557 int status
= JAR_ERR_PNF
;
559 list
= signer
->certs
;
563 if (ZZ_ListEmpty (list
))
569 for (link
= ZZ_ListHead (list
);
570 !ZZ_ListIterDone (list
, link
);
573 if (link
->thing
->type
== type
)
584 JAR_Signer
*JAR_new_signer (void)
588 signer
= (JAR_Signer
*) PORT_ZAlloc (sizeof (JAR_Signer
));
595 signer
->certs
= ZZ_NewList();
597 if (signer
->certs
== NULL
)
602 signer
->sf
= ZZ_NewList();
604 if (signer
->sf
== NULL
)
616 ZZ_DestroyList (signer
->certs
);
619 ZZ_DestroyList (signer
->sf
);
627 void JAR_destroy_signer (JAR_Signer
*signer
)
631 if (signer
->owner
) PORT_Free (signer
->owner
);
632 if (signer
->digest
) PORT_Free (signer
->digest
);
634 jar_destroy_list (signer
->sf
);
635 ZZ_DestroyList (signer
->sf
);
637 jar_destroy_list (signer
->certs
);
638 ZZ_DestroyList (signer
->certs
);
644 JAR_Signer
*jar_get_signer (JAR
*jar
, char *basename
)
649 JAR_Signer
*candidate
;
650 JAR_Signer
*signer
= NULL
;
652 ctx
= JAR_find (jar
, NULL
, jarTypeOwner
);
657 while (JAR_find_next (ctx
, &it
) >= 0)
659 candidate
= (JAR_Signer
*) it
->data
;
660 if (*basename
== '*' || !PORT_Strcmp (candidate
->owner
, basename
))
673 * J A R _ g e t _ f i l e n a m e
675 * Returns the filename associated with
680 char *JAR_get_filename (JAR
*jar
)
682 return jar
->filename
;
686 * J A R _ g e t _ u r l
688 * Returns the URL associated with
689 * a JAR structure. Nobody really uses this now.
693 char *JAR_get_url (JAR
*jar
)
699 * J A R _ s e t _ c a l l b a c k
701 * Register some manner of callback function for this jar.
705 int JAR_set_callback (int type
, JAR
*jar
,
706 int (*fn
) (int status
, JAR
*jar
,
707 const char *metafile
, char *pathname
, char *errortext
))
709 if (type
== JAR_CB_SIGNAL
)
723 /* To return an error string */
724 char *(*jar_fn_GetString
) (int) = NULL
;
726 /* To return an MWContext for Java */
727 void *(*jar_fn_FindSomeContext
) (void) = NULL
;
729 /* To fabricate an MWContext for FE_GetPassword */
730 void *(*jar_fn_GetInitContext
) (void) = NULL
;
735 char *(*string_cb
)(int),
736 void *(*find_cx
)(void),
737 void *(*init_cx
)(void)
740 jar_fn_GetString
= string_cb
;
741 jar_fn_FindSomeContext
= find_cx
;
742 jar_fn_GetInitContext
= init_cx
;
746 * J A R _ g e t _ e r r o r
748 * This is provided to map internal JAR errors to strings for
749 * the Java console. Also, a DLL may call this function if it does
750 * not have access to the XP_GetString function.
752 * These strings aren't UI, since they are Java console only.
756 char *JAR_get_error (int status
)
758 char *errstring
= NULL
;
762 case JAR_ERR_GENERAL
:
763 errstring
= "General JAR file error";
767 errstring
= "JAR file not found";
770 case JAR_ERR_CORRUPT
:
771 errstring
= "Corrupt JAR file";
775 errstring
= "Out of memory";
779 errstring
= "Disk error (perhaps out of space)";
783 errstring
= "Inconsistent files in META-INF directory";
787 errstring
= "Invalid digital signature file";
790 case JAR_ERR_METADATA
:
791 errstring
= "JAR metadata failed verification";
795 errstring
= "No Manifest entry for this JAR entry";
799 errstring
= "Invalid Hash of this JAR entry";
803 errstring
= "Strange PKCS7 or RSA failure";
807 errstring
= "Path not found inside JAR file";
811 if (jar_fn_GetString
)
813 errstring
= jar_fn_GetString (status
);
817 /* this is not a normal situation, and would only be
818 called in cases of improper initialization */
822 err
= (char*)PORT_Alloc (40);
824 PR_snprintf (err
, 39, "Error %d\n", status
);
826 err
= "Error! Bad! Out of memory!";