Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions
jarver.c File Reference
#include "jar.h"
#include "jarint.h"
#include "jarevil.h"
#include "secder.h"

Go to the source code of this file.

Defines

#define USE_MOZ_THREAD
#define xp_HUGE_MEMCPY   PORT_Memcpy
#define xp_HUGE_STRCPY   PORT_Strcpy
#define xp_HUGE_STRLEN   PORT_Strlen
#define xp_HUGE_STRNCASECMP   PORT_Strncasecmp
#define CERTDB_USER   (1<<6)
#define SZ   512
#define SEP   " <br> "
#define SEPLEN   (PORT_Strlen(SEP))

Functions

static int jar_validate_pkcs7 (JAR *jar, JAR_Signer *signer, 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 ZHUGEPjar_eat_line (int lines, int eating, char ZHUGEP *data, long *len)
static JAR_Digestjar_digest_section (char ZHUGEP *manifest, long length)
static JAR_Digestjar_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)
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)
int JAR_parse_manifest (JAR *jar, char ZHUGEP *raw_manifest, long length, const char *path, const char *url)
int PR_CALLBACK JAR_verify_digest (JAR *jar, const char *name, JAR_Digest *dig)
int PR_CALLBACK JAR_cert_attribute (JAR *jar, jarCert attrib, long keylen, void *key, void **result, unsigned long *length)
char * JAR_cert_html (JAR *jar, int style, long keylen, void *key, int *result)
int PR_CALLBACK JAR_stash_cert (JAR *jar, long keylen, void *key)
voidJAR_fetch_cert (long length, void *key)
CERTCertDBHandle * JAR_open_database (void)
int JAR_close_database (CERTCertDBHandle *certdb)
int jar_append (ZZList *list, int type, char *pathname, void *data, size_t size)

Define Documentation

#define CERTDB_USER   (1<<6)

Definition at line 69 of file jarver.c.

#define SEP   " <br> "
#define SZ   512

Definition at line 71 of file jarver.c.

Definition at line 43 of file jarver.c.

Definition at line 57 of file jarver.c.

Definition at line 58 of file jarver.c.

Definition at line 59 of file jarver.c.

Definition at line 60 of file jarver.c.


Function Documentation

static int jar_add_cert ( JAR jar,
JAR_Signer signer,
int  type,
CERTCertificate *  cert 
) [static]

Definition at line 843 of file jarver.c.

  {
  JAR_Cert *fing;
  unsigned char *keyData;

  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->derIssuer.len + 2 + cert->serialNumber.len;

  keyData = (unsigned char *) PORT_ZAlloc (fing->length);
  fing->key = keyData;

  if (fing->key == NULL)
    goto loser;
  keyData[0] = ((cert->derIssuer.len) >> 8) & 0xff;
  keyData[1] = ((cert->derIssuer.len) & 0xff);
  PORT_Memcpy (&keyData[2], cert->derIssuer.data, cert->derIssuer.len);
  PORT_Memcpy (&keyData[2+cert->derIssuer.len], cert->serialNumber.data,
                                           cert->serialNumber.len);

  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int jar_append ( ZZList *  list,
int  type,
char *  pathname,
void data,
size_t  size 
)

Definition at line 1938 of file jarver.c.

  {
  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;
  }
static char * jar_basename ( const char *  path) [static]

Definition at line 1592 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static void jar_catch_bytes ( void arg,
const char *  buf,
unsigned long  len 
) [static]

Definition at line 1643 of file jarver.c.

  {
  /* Actually this should never be called, since there is
     presumably no data in the signature itself. */
  }

Here is the caller graph for this function:

int PR_CALLBACK JAR_cert_attribute ( JAR jar,
jarCert  attrib,
long  keylen,
void key,
void **  result,
unsigned long length 
)

Definition at line 1060 of file jarver.c.

  {
  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;
  }
static char * jar_cert_element ( char *  name,
char *  tag,
int  occ 
) [static]

Definition at line 1268 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

char* JAR_cert_html ( JAR jar,
int  style,
long  keylen,
void key,
int result 
)

Definition at line 1381 of file jarver.c.

  {
#ifdef notdef
  char *html;
#endif
  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 = -1;

   return NULL;

#ifdef notdef
  html = CERT_HTMLCertInfo (cert, /* show images */ PR_TRUE,
              /*show issuer*/PR_TRUE);

  if (html == NULL)
    *result = -1;

  return html;
#endif
  }
static char * jar_choose_nickname ( CERTCertificate *  cert) [static]

Definition at line 1319 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int JAR_close_database ( CERTCertDBHandle *  certdb)

Definition at line 1832 of file jarver.c.

  {
#ifdef notdef
  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);
#endif

  return 0;
  }
static JAR_Digest * jar_digest_section ( char ZHUGEP manifest,
long  length 
) [static]

Definition at line 964 of file jarver.c.

  {
  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);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static char ZHUGEP * jar_eat_line ( int  lines,
int  eating,
char ZHUGEP data,
long len 
) [static]

Definition at line 905 of file jarver.c.

  {
  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;
  }

Here is the caller graph for this function:

void* JAR_fetch_cert ( long  length,
void key 
)

Definition at line 1517 of file jarver.c.

  {
  CERTIssuerAndSN issuerSN;
  CERTCertificate *cert = NULL;

  CERTCertDBHandle *certdb;

  certdb = JAR_open_database();

  if (certdb)
    {
    unsigned char *keyData = (unsigned char *)key;
    issuerSN.derIssuer.len = (keyData[0] << 8) + keyData[0];
    issuerSN.derIssuer.data = &keyData[2];
    issuerSN.serialNumber.len = length - (2 + issuerSN.derIssuer.len);
    issuerSN.serialNumber.data = &keyData[2+issuerSN.derIssuer.len];

#ifdef USE_MOZ_THREAD
    cert = jar_moz_certkey (certdb, &issuerSN);
#else
    cert = CERT_FindCertByIssuerAndSN (certdb, &issuerSN);
#endif

    JAR_close_database (certdb);
    }

  return (void *) cert;
  }
static int jar_gather_signers ( JAR jar,
JAR_Signer signer,
SEC_PKCS7ContentInfo *  cinfo 
) [static]

Definition at line 1767 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static CERTCertificate * jar_get_certificate ( JAR jar,
long  keylen,
void key,
int result 
) [static]

Definition at line 1860 of file jarver.c.

  {
  int found = 0;

  JAR_Item *it;
  JAR_Cert *fing = NULL;

  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;
    }

  PORT_Assert(fing != NULL);
  *result = 0;
  return fing->cert;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static JAR_Digest * jar_get_mf_digest ( JAR jar,
char *  path 
) [static]

Definition at line 1554 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static int jar_internal_digest ( JAR jar,
const char *  path,
char *  x_name,
JAR_Digest dig 
) [static]

Definition at line 722 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

CERTCertDBHandle* JAR_open_database ( void  )

Definition at line 1815 of file jarver.c.

  {
  CERTCertDBHandle *certdb;

  certdb = CERT_GetDefaultCertDB();

  return certdb;
  }
int jar_parse_any ( JAR jar,
int  type,
JAR_Signer signer,
char ZHUGEP raw_manifest,
long  length,
const char *  path,
const char *  url 
)

Definition at line 397 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static int jar_parse_digital_signature ( char *  raw_manifest,
JAR_Signer signer,
long  length,
JAR jar 
) [static]

Definition at line 824 of file jarver.c.

  {
#if defined(XP_WIN16)
  PORT_Assert( LOWORD(raw_manifest) + length < 0xFFFF );
#endif
  return jar_validate_pkcs7 (jar, signer, raw_manifest, length);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int JAR_parse_manifest ( JAR jar,
char ZHUGEP raw_manifest,
long  length,
const char *  path,
const char *  url 
)

Definition at line 142 of file jarver.c.

  {

#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);
    }
  }
int jar_parse_mf ( JAR jar,
char ZHUGEP raw_manifest,
long  length,
const char *  path,
const char *  url 
)

Definition at line 297 of file jarver.c.

  {
  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);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int jar_parse_sf ( JAR jar,
char ZHUGEP raw_manifest,
long  length,
const char *  path,
const char *  url 
)

Definition at line 328 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int jar_parse_sig ( JAR jar,
const char *  path,
char ZHUGEP raw_manifest,
long  length 
)

Definition at line 197 of file jarver.c.

  {
  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

static int jar_signal ( int  status,
JAR jar,
const char *  metafile,
char *  pathname 
) [static]

Definition at line 1915 of file jarver.c.

  {
  char *errstring;

  errstring = JAR_get_error (status);

  if (jar->signal)
    {
    (*jar->signal) (status, jar, metafile, pathname, errstring);
    return 0;
    }

  return status;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int PR_CALLBACK JAR_stash_cert ( JAR jar,
long  keylen,
void key 
)

Definition at line 1422 of file jarver.c.

  {
  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;
  }
static int jar_validate_pkcs7 ( JAR jar,
JAR_Signer signer,
char *  data,
long  length 
) [static]

Definition at line 1658 of file jarver.c.

  {
  SECItem detdig;

  SEC_PKCS7ContentInfo *cinfo = NULL;
  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_OLD
  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) 
    {
    /* strange pkcs7 failure */
    return JAR_ERR_PK7;
    }

  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;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

int PR_CALLBACK JAR_verify_digest ( JAR jar,
const char *  name,
JAR_Digest dig 
)

Definition at line 991 of file jarver.c.

  {
  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;
  }