security/nss/lib/jar/jar.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  *  JAR.C
     7  *
     8  *  Jarnature.
     9  *  Routines common to signing and validating.
    10  *
    11  */
    13 #include "jar.h"
    14 #include "jarint.h"
    15 #include "portreg.h"
    17 static void 
    18 jar_destroy_list (ZZList *list);
    20 static int 
    21 jar_find_first_cert(JAR_Signer *signer, int type, JAR_Item **it);
    23 /*
    24  *  J A R _ n e w
    25  *
    26  *  Create a new instantiation of a manifest representation.
    27  *  Use this as a token to any calls to this API.
    28  *
    29  */
    30 JAR *
    31 JAR_new(void)
    32 {
    33     JAR *jar;
    35     if ((jar = (JAR*)PORT_ZAlloc (sizeof (JAR))) == NULL)
    36 	goto loser;
    37     if ((jar->manifest = ZZ_NewList()) == NULL)
    38 	goto loser;
    39     if ((jar->hashes = ZZ_NewList()) == NULL)
    40 	goto loser;
    41     if ((jar->phy = ZZ_NewList()) == NULL)
    42 	goto loser;
    43     if ((jar->metainfo = ZZ_NewList()) == NULL)
    44 	goto loser;
    45     if ((jar->signers = ZZ_NewList()) == NULL)
    46 	goto loser;
    47     return jar;
    49 loser:
    50     if (jar) {
    51 	if (jar->manifest)
    52 	    ZZ_DestroyList (jar->manifest);
    53 	if (jar->hashes)
    54 	    ZZ_DestroyList (jar->hashes);
    55 	if (jar->phy)
    56 	    ZZ_DestroyList (jar->phy);
    57 	if (jar->metainfo)
    58 	    ZZ_DestroyList (jar->metainfo);
    59 	if (jar->signers)
    60 	    ZZ_DestroyList (jar->signers);
    61 	PORT_Free (jar);
    62     }
    63     return NULL;
    64 }
    66 /*
    67  *  J A R _ d e s t r o y
    68  */
    69 void PR_CALLBACK 
    70 JAR_destroy(JAR *jar)
    71 {
    72     PORT_Assert( jar != NULL );
    74     if (jar == NULL)
    75 	return;
    77     if (jar->fp) 
    78     	JAR_FCLOSE ((PRFileDesc*)jar->fp);
    79     if (jar->url)      
    80     	PORT_Free (jar->url);
    81     if (jar->filename) 
    82     	PORT_Free (jar->filename);
    84     /* Free the linked list elements */
    85     jar_destroy_list (jar->manifest);
    86     ZZ_DestroyList (jar->manifest);
    87     jar_destroy_list (jar->hashes);
    88     ZZ_DestroyList (jar->hashes);
    89     jar_destroy_list (jar->phy);
    90     ZZ_DestroyList (jar->phy);
    91     jar_destroy_list (jar->metainfo);
    92     ZZ_DestroyList (jar->metainfo);
    93     jar_destroy_list (jar->signers);
    94     ZZ_DestroyList (jar->signers);
    95     PORT_Free (jar);
    96 }
    98 static void 
    99 jar_destroy_list(ZZList *list)
   100 {
   101     ZZLink *link, *oldlink;
   102     JAR_Item *it;
   103     JAR_Physical *phy;
   104     JAR_Digest *dig;
   105     JAR_Cert *fing;
   106     JAR_Metainfo *met;
   107     JAR_Signer *signer;
   109     if (list && !ZZ_ListEmpty (list)) {
   110 	link = ZZ_ListHead (list);
   111 	while (!ZZ_ListIterDone (list, link)) {
   112 	    it = link->thing;
   113 	    if (!it) 
   114 	    	goto next;
   115 	    if (it->pathname) 
   116 	    	PORT_Free (it->pathname);
   118 	    switch (it->type) {
   119 	    case jarTypeMeta:
   120 		met = (JAR_Metainfo *) it->data;
   121 		if (met) {
   122 		    if (met->header) 
   123 		    	PORT_Free (met->header);
   124 		    if (met->info) 
   125 		    	PORT_Free (met->info);
   126 		    PORT_Free (met);
   127 		}
   128 		break;
   130 	    case jarTypePhy:
   131 		phy = (JAR_Physical *) it->data;
   132 		if (phy)
   133 		    PORT_Free (phy);
   134 		break;
   136 	    case jarTypeSign:
   137 		fing = (JAR_Cert *) it->data;
   138 		if (fing) {
   139 		    if (fing->cert)
   140 			CERT_DestroyCertificate (fing->cert);
   141 		    if (fing->key)
   142 			PORT_Free (fing->key);
   143 		    PORT_Free (fing);
   144 		}
   145 		break;
   147 	    case jarTypeSect:
   148 	    case jarTypeMF:
   149 	    case jarTypeSF:
   150 		dig = (JAR_Digest *) it->data;
   151 		if (dig) {
   152 		    PORT_Free (dig);
   153 		}
   154 		break;
   156 	    case jarTypeOwner:
   157 		signer = (JAR_Signer *) it->data;
   158 		if (signer)
   159 		    JAR_destroy_signer (signer);
   160 		break;
   162 	    default:
   163 		/* PORT_Assert( 1 != 2 ); */
   164 		break;
   165 	    }
   166 	    PORT_Free (it);
   168 next:
   169 	    oldlink = link;
   170 	    link = link->next;
   171 	    ZZ_DestroyLink (oldlink);
   172 	}
   173     }
   174 }
   176 /*
   177  *  J A R _ g e t _ m e t a i n f o
   178  *
   179  *  Retrieve meta information from the manifest file.
   180  *  It doesn't matter whether it's from .MF or .SF, does it?
   181  *
   182  */
   184 int 
   185 JAR_get_metainfo(JAR *jar, char *name, char *header, void **info, 
   186                  unsigned long *length)
   187 {
   188     JAR_Item *it;
   189     ZZLink *link;
   190     ZZList *list;
   192     PORT_Assert( jar != NULL && header != NULL );
   194     if (jar == NULL || header == NULL)
   195 	return JAR_ERR_PNF;
   197     list = jar->metainfo;
   199     if (ZZ_ListEmpty (list))
   200 	return JAR_ERR_PNF;
   202     for (link = ZZ_ListHead (list);
   203          !ZZ_ListIterDone (list, link);
   204          link = link->next) {
   205 	it = link->thing;
   206 	if (it->type == jarTypeMeta) {
   207 	    JAR_Metainfo *met;
   209 	    if ((name && !it->pathname) || (!name && it->pathname))
   210 		continue;
   211 	    if (name && it->pathname && strcmp (it->pathname, name))
   212 		continue;
   213 	    met = (JAR_Metainfo *) it->data;
   214 	    if (!PORT_Strcasecmp (met->header, header)) {
   215 		*info = PORT_Strdup (met->info);
   216 		*length = PORT_Strlen (met->info);
   217 		return 0;
   218 	    }
   219 	}
   220     }
   221     return JAR_ERR_PNF;
   222 }
   224 /*
   225  *  J A R _ f i n d
   226  *
   227  *  Establish the search pattern for use
   228  *  by JAR_find_next, to traverse the filenames
   229  *  or certificates in the JAR structure.
   230  *
   231  *  See jar.h for a description on how to use.
   232  *
   233  */
   234 JAR_Context *
   235 JAR_find (JAR *jar, char *pattern, jarType type)
   236 {
   237     JAR_Context *ctx;
   239     PORT_Assert( jar != NULL );
   241     if (!jar)
   242 	return NULL;
   244     ctx = (JAR_Context *) PORT_ZAlloc (sizeof (JAR_Context));
   245     if (ctx == NULL)
   246 	return NULL;
   248     ctx->jar = jar;
   249     if (pattern) {
   250 	if ((ctx->pattern = PORT_Strdup (pattern)) == NULL) {
   251 	    PORT_Free (ctx);
   252 	    return NULL;
   253 	}
   254     }
   255     ctx->finding = type;
   257     switch (type) {
   258     case jarTypeMF:
   259 	ctx->next = ZZ_ListHead (jar->hashes);
   260 	break;
   262     case jarTypeSF:
   263     case jarTypeSign:
   264 	ctx->next = NULL;
   265 	ctx->nextsign = ZZ_ListHead (jar->signers);
   266 	break;
   268     case jarTypeSect:
   269 	ctx->next = ZZ_ListHead (jar->manifest);
   270 	break;
   272     case jarTypePhy:
   273 	ctx->next = ZZ_ListHead (jar->phy);
   274 	break;
   276     case jarTypeOwner:
   277 	if (jar->signers)
   278 	    ctx->next = ZZ_ListHead (jar->signers);
   279 	else
   280 	    ctx->next = NULL;
   281 	break;
   283     case jarTypeMeta:
   284 	ctx->next = ZZ_ListHead (jar->metainfo);
   285 	break;
   287     default:
   288 	PORT_Assert( 1 != 2);
   289 	break;
   290     }
   291     return ctx;
   292 }
   294 /*
   295  *  J A R _ f i n d _ e n d
   296  *
   297  *  Destroy the find iterator context.
   298  *
   299  */
   300 void 
   301 JAR_find_end (JAR_Context *ctx)
   302 {
   303     PORT_Assert( ctx != NULL );
   304     if (ctx) {
   305 	if (ctx->pattern)
   306 	    PORT_Free (ctx->pattern);
   307 	PORT_Free (ctx);
   308     }
   309 }
   311 /*
   312  *  J A R _ f i n d _ n e x t
   313  *
   314  *  Return the next item of the given type
   315  *  from one of the JAR linked lists.
   316  *
   317  */
   319 int JAR_find_next (JAR_Context *ctx, JAR_Item **it)
   320 {
   321     JAR *jar;
   322     ZZList *list = NULL;
   323     int finding;
   324     JAR_Signer *signer = NULL;
   326     PORT_Assert( ctx != NULL );
   327     PORT_Assert( ctx->jar != NULL );
   329     jar = ctx->jar;
   331     /* Internally, convert jarTypeSign to jarTypeSF, and return
   332        the actual attached certificate later */
   333     finding = (ctx->finding == jarTypeSign) ? jarTypeSF : ctx->finding;
   334     if (ctx->nextsign) {
   335 	if (ZZ_ListIterDone (jar->signers, ctx->nextsign)) {
   336 	    *it = NULL;
   337 	    return -1;
   338 	}
   339 	PORT_Assert (ctx->nextsign->thing != NULL);
   340 	signer = (JAR_Signer*)ctx->nextsign->thing->data;
   341     }
   343     /* Find out which linked list to traverse. Then if
   344        necessary, advance to the next linked list. */
   345     while (1) {
   346 	switch (finding) {
   347 	case jarTypeSign:    /* not any more */
   348 	    PORT_Assert( finding != jarTypeSign );
   349 	    list = signer->certs;
   350 	    break;
   352 	case jarTypeSect:
   353 	    list = jar->manifest;
   354 	    break;
   356 	case jarTypePhy:
   357 	    list = jar->phy;
   358 	    break;
   360 	case jarTypeSF:      /* signer, not jar */
   361 	    PORT_Assert( signer != NULL );
   362 	    list = signer ? signer->sf : NULL;
   363 	    break;
   365 	case jarTypeMF:
   366 	    list = jar->hashes;
   367 	    break;
   369 	case jarTypeOwner:
   370 	    list = jar->signers;
   371 	    break;
   373 	case jarTypeMeta:
   374 	    list = jar->metainfo;
   375 	    break;
   377 	default:
   378 	    PORT_Assert( 1 != 2 );
   379 	    list = NULL;
   380 	    break;
   381 	}
   382 	if (list == NULL) {
   383 	    *it = NULL;
   384 	    return -1;
   385 	}
   386 	/* When looping over lists of lists, advance to the next signer. 
   387 	   This is done when multiple signers are possible. */
   388 	if (ZZ_ListIterDone (list, ctx->next)) {
   389 	    if (ctx->nextsign && jar->signers) {
   390 		ctx->nextsign = ctx->nextsign->next;
   391 		if (!ZZ_ListIterDone (jar->signers, ctx->nextsign)) {
   392 		    PORT_Assert (ctx->nextsign->thing != NULL);
   393 		    signer = (JAR_Signer*)ctx->nextsign->thing->data;
   394 		    PORT_Assert( signer != NULL );
   395 		    ctx->next = NULL;
   396 		    continue;
   397 		}
   398 	    }
   399 	    *it = NULL;
   400 	    return -1;
   401 	}
   403 	/* if the signer changed, still need to fill in the "next" link */
   404 	if (ctx->nextsign && ctx->next == NULL) {
   405 	    switch (finding) {
   406 	    case jarTypeSF:
   407 		ctx->next = ZZ_ListHead (signer->sf);
   408 		break;
   410 	    case jarTypeSign:
   411 		ctx->next = ZZ_ListHead (signer->certs);
   412 		break;
   413 	    }
   414 	}
   415 	PORT_Assert( ctx->next != NULL );
   416 	if (ctx->next == NULL) {
   417 	    *it = NULL;
   418 	    return -1;
   419 	}
   420 	while (!ZZ_ListIterDone (list, ctx->next)) {
   421 	    *it = ctx->next->thing;
   422 	    ctx->next = ctx->next->next;
   423 	    if (!*it || (*it)->type != finding)
   424 		continue;
   425 	    if (ctx->pattern && *ctx->pattern) {
   426 		if (PORT_RegExpSearch ((*it)->pathname, ctx->pattern))
   427 		    continue;
   428 	    }
   429 	    /* We have a valid match. If this is a jarTypeSign
   430 	       return the certificate instead.. */
   431 	    if (ctx->finding == jarTypeSign) {
   432 		JAR_Item *itt;
   434 		/* just the first one for now */
   435 		if (jar_find_first_cert (signer, jarTypeSign, &itt) >= 0) {
   436 		    *it = itt;
   437 		    return 0;
   438 		}
   439 		continue;
   440 	    }
   441 	    return 0;
   442 	}
   443     } /* end while */
   444 }
   446 static int 
   447 jar_find_first_cert (JAR_Signer *signer, int type, JAR_Item **it)
   448 {
   449     ZZLink *link;
   450     ZZList *list = signer->certs;
   451     int status = JAR_ERR_PNF;
   453     *it = NULL;
   454     if (ZZ_ListEmpty (list)) {
   455 	/* empty list */
   456 	return JAR_ERR_PNF;
   457     }
   459     for (link = ZZ_ListHead (list);
   460 	 !ZZ_ListIterDone (list, link);
   461 	 link = link->next) {
   462 	if (link->thing->type == type) {
   463 	    *it = link->thing;
   464 	    status = 0;
   465 	    break;
   466 	}
   467     }
   468     return status;
   469 }
   471 JAR_Signer *
   472 JAR_new_signer (void) 
   473 {
   474     JAR_Signer *signer = (JAR_Signer *) PORT_ZAlloc (sizeof (JAR_Signer));
   475     if (signer == NULL)
   476 	goto loser;
   478     /* certs */
   479     signer->certs = ZZ_NewList();
   480     if (signer->certs == NULL)
   481 	goto loser;
   483     /* sf */
   484     signer->sf = ZZ_NewList();
   485     if (signer->sf == NULL)
   486 	goto loser;
   487     return signer;
   489 loser:
   490     if (signer) {
   491 	if (signer->certs)
   492 	    ZZ_DestroyList (signer->certs);
   493 	if (signer->sf)
   494 	    ZZ_DestroyList (signer->sf);
   495 	PORT_Free (signer);
   496     }
   497     return NULL;
   498 }
   500 void 
   501 JAR_destroy_signer(JAR_Signer *signer)
   502 {
   503     if (signer) {
   504 	if (signer->owner) 
   505 	    PORT_Free (signer->owner);
   506 	if (signer->digest) 
   507 	    PORT_Free (signer->digest);
   508 	jar_destroy_list (signer->sf);
   509 	ZZ_DestroyList (signer->sf);
   510 	jar_destroy_list (signer->certs);
   511 	ZZ_DestroyList (signer->certs);
   512 	PORT_Free (signer);
   513     }
   514 }
   516 JAR_Signer *
   517 jar_get_signer(JAR *jar, char *basename)
   518 {
   519     JAR_Item *it;
   520     JAR_Context *ctx = JAR_find (jar, NULL, jarTypeOwner);
   521     JAR_Signer *candidate;
   522     JAR_Signer *signer = NULL;
   524     if (ctx == NULL)
   525 	return NULL;
   527     while (JAR_find_next (ctx, &it) >= 0) {
   528 	candidate = (JAR_Signer *) it->data;
   529 	if (*basename == '*' || !PORT_Strcmp (candidate->owner, basename)) {
   530 	    signer = candidate;
   531 	    break;
   532 	}
   533     }
   534     JAR_find_end (ctx);
   535     return signer;
   536 }
   538 /*
   539  *  J A R _ g e t _ f i l e n a m e
   540  *
   541  *  Returns the filename associated with
   542  *  a JAR structure.
   543  *
   544  */
   545 char *
   546 JAR_get_filename(JAR *jar)
   547 {
   548     return jar->filename;
   549 }
   551 /*
   552  *  J A R _ g e t _ u r l
   553  *
   554  *  Returns the URL associated with
   555  *  a JAR structure. Nobody really uses this now.
   556  *
   557  */
   558 char *
   559 JAR_get_url(JAR *jar)
   560 {
   561     return jar->url;
   562 }
   564 /*
   565  *  J A R _ s e t _ c a l l b a c k
   566  *
   567  *  Register some manner of callback function for this jar.
   568  *
   569  */
   570 int 
   571 JAR_set_callback(int type, JAR *jar, jar_settable_callback_fn *fn)
   572 {
   573     if (type == JAR_CB_SIGNAL) {
   574 	jar->signal = fn;
   575 	return 0;
   576     }
   577     return -1;
   578 }
   580 /*
   581  *  Callbacks
   582  *
   583  */
   585 /* To return an error string */
   586 char *(*jar_fn_GetString) (int) = NULL;
   588 /* To return an MWContext for Java */
   589 void *(*jar_fn_FindSomeContext) (void) = NULL;
   591 /* To fabricate an MWContext for FE_GetPassword */
   592 void *(*jar_fn_GetInitContext) (void) = NULL;
   594 void
   595 JAR_init_callbacks(char *(*string_cb)(int), 
   596                    void *(*find_cx)(void),
   597                    void *(*init_cx)(void))
   598 {
   599     jar_fn_GetString = string_cb;
   600     jar_fn_FindSomeContext = find_cx;
   601     jar_fn_GetInitContext = init_cx;
   602 }
   604 /*
   605  *  J A R _ g e t _ e r r o r
   606  *
   607  *  This is provided to map internal JAR errors to strings for
   608  *  the Java console. Also, a DLL may call this function if it does
   609  *  not have access to the XP_GetString function.
   610  *
   611  *  These strings aren't UI, since they are Java console only.
   612  *
   613  */
   614 char *
   615 JAR_get_error(int status)
   616 {
   617     char *errstring = NULL;
   619     switch (status) {
   620     case JAR_ERR_GENERAL:
   621 	errstring = "General JAR file error";
   622 	break;
   624     case JAR_ERR_FNF:
   625 	errstring = "JAR file not found";
   626 	break;
   628     case JAR_ERR_CORRUPT:
   629 	errstring = "Corrupt JAR file";
   630 	break;
   632     case JAR_ERR_MEMORY:
   633 	errstring = "Out of memory";
   634 	break;
   636     case JAR_ERR_DISK:
   637 	errstring = "Disk error (perhaps out of space)";
   638 	break;
   640     case JAR_ERR_ORDER:
   641 	errstring = "Inconsistent files in META-INF directory";
   642 	break;
   644     case JAR_ERR_SIG:
   645 	errstring = "Invalid digital signature file";
   646 	break;
   648     case JAR_ERR_METADATA:
   649 	errstring = "JAR metadata failed verification";
   650 	break;
   652     case JAR_ERR_ENTRY:
   653 	errstring = "No Manifest entry for this JAR entry";
   654 	break;
   656     case JAR_ERR_HASH:
   657 	errstring = "Invalid Hash of this JAR entry";
   658 	break;
   660     case JAR_ERR_PK7:
   661 	errstring = "Strange PKCS7 or RSA failure";
   662 	break;
   664     case JAR_ERR_PNF:
   665 	errstring = "Path not found inside JAR file";
   666 	break;
   668     default:
   669 	if (jar_fn_GetString) {
   670 	    errstring = jar_fn_GetString (status);
   671 	} else {
   672 	    /* this is not a normal situation, and would only be
   673 	       called in cases of improper initialization */
   674 	    char *err = (char*)PORT_Alloc (40);
   675 	    if (err)
   676 		PR_snprintf (err, 39,  "Error %d\n", status); /* leak me! */
   677 	    else
   678 		err = "Error! Bad! Out of memory!";
   679 	    return err;
   680 	}
   681 	break;
   682     }
   683     return errstring;
   684 }

mercurial