jar.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:16k
源码类别:

CA认证

开发平台:

WINDOWS

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