jarver.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,030 行 · 第 1/3 页
C
2,030 行
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; }static int jar_internal_digest (JAR *jar, const char *path, char *x_name, JAR_Digest *dig) { 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; }#ifdef DEBUG/* * j a r _ i n s a n i t y _ c h e c k * * Check for illegal characters (or possibly so) * in the manifest files, to detect potential memory * corruption by our neighbors. Debug only, since * not I18N safe. * */static int jar_insanity_check (char ZHUGEP *data, long length) { int c; long off; for (off = 0; off < length; off++) { c = data [off]; if (c == '\n' || c == '\r' || (c >= ' ' && c <= 128)) continue; return JAR_ERR_CORRUPT; } return 0; }#endif/* * j a r _ p a r s e _ d i g i t a l _ s i g n a t u r e * * Parse an RSA or DSA (or perhaps other) digital signature. * Right now everything is PKCS7. * */static int jar_parse_digital_signature (char *raw_manifest, JAR_Signer *signer, long length, JAR *jar) {#if defined(XP_WIN16) PORT_Assert( LOWORD(raw_manifest) + length < 0xFFFF );#endif return jar_validate_pkcs7 (jar, signer, raw_manifest, length); }/* * j a r _ a d d _ c e r t * * Add information for the given certificate * (or whatever) to the JAR linked list. A pointer * is passed for some relevant reference, say * for example the original certificate. * */static int jar_add_cert (JAR *jar, JAR_Signer *signer, int type, CERTCertificate *cert) { JAR_Cert *fing; 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->certKey.len; fing->key = (char *) PORT_ZAlloc (fing->length); if (fing->key == NULL) goto loser; PORT_Memcpy (fing->key, cert->certKey.data, fing->length); 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; }/* * e a t _ l i n e * * Consume an ascii line from the top of a file kept * in memory. This destroys the file in place. This function * handles PC, Mac, and Unix style text files. * */static char ZHUGEP *jar_eat_line (int lines, int eating, char ZHUGEP *data, long *len) { 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; }/* * j a r _ d i g e s t _ s e c t i o n * * Return the digests of the next section of the manifest file. * Does not damage the manifest file, unlike parse_manifest. * */static JAR_Digest *jar_digest_section (char ZHUGEP *manifest, long length) { 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); }/* * J A R _ v e r i f y _ d i g e s t * * Verifies that a precalculated digest matches the * expected value in the manifest. * */int PR_CALLBACK JAR_verify_digest (JAR *jar, const char *name, JAR_Digest *dig) { 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; }/* * J A R _ c e r t _ a t t r i b u t e * * Return the named certificate attribute from the * certificate specified by the given key. * */int PR_CALLBACK JAR_cert_attribute (JAR *jar, jarCert attrib, long keylen, void *key, void **result, unsigned long *length) { 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; }/* * j a r _ c e r t _ e l e m e n t * * Retrieve an element from an x400ish ascii * designator, in a hackish sort of way. The right * thing would probably be to sort AVATags. * */static char *jar_cert_element (char *name, char *tag, int occ) { 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; }/* * j a r _ c h o o s e _ n i c k n a m e * * Attempt to determine a suitable nickname for * a certificate with a computer-generated "tmpcertxxx" * nickname. It needs to be something a user can * understand, so try a few things. * */static char *jar_choose_nickname (CERTCertificate *cert) { 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?