| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #ifndef __JAR_h_ |
| #define __JAR_h_ |
| |
| /* |
| * In general, any functions that return pointers |
| * have memory owned by the caller. |
| * |
| */ |
| |
| /* security includes */ |
| #include "cert.h" |
| #include "hasht.h" |
| |
| /* nspr 2.0 includes */ |
| #include "prio.h" |
| |
| #define ZHUGEP |
| |
| #include <stdio.h> |
| |
| /* various types */ |
| |
| typedef enum { |
| jarTypeMF = 2, |
| jarTypeSF = 3, |
| jarTypeMeta = 6, |
| jarTypePhy = 7, |
| jarTypeSign = 10, |
| jarTypeSect = 11, |
| jarTypeOwner = 13 |
| } jarType; |
| |
| /* void data in ZZList's contain JAR_Item type */ |
| typedef struct JAR_Item_ { |
| char *pathname; /* relative. inside zip file */ |
| jarType type; /* various types */ |
| size_t size; /* size of data below */ |
| void *data; /* totally opaque */ |
| } JAR_Item; |
| |
| /* hashes */ |
| typedef enum { |
| jarHashNone = 0, |
| jarHashBad = 1, |
| jarHashPresent = 2 |
| } jarHash; |
| |
| typedef struct JAR_Digest_ { |
| jarHash md5_status; |
| unsigned char md5[MD5_LENGTH]; |
| jarHash sha1_status; |
| unsigned char sha1[SHA1_LENGTH]; |
| } JAR_Digest; |
| |
| /* physical archive formats */ |
| typedef enum { |
| jarArchGuess = 0, |
| jarArchNone = 1, |
| jarArchZip = 2, |
| jarArchTar = 3 |
| } jarArch; |
| |
| #include "jar-ds.h" |
| |
| struct JAR_; |
| |
| typedef int jar_settable_callback_fn(int status, struct JAR_ *jar, |
| const char *metafile, char *pathname, |
| char *errortext); |
| |
| /* jar object */ |
| typedef struct JAR_ { |
| jarArch format; /* physical archive format */ |
| |
| char *url; /* Where it came from */ |
| char *filename; /* Disk location */ |
| FILE *fp; /* For multiple extractions */ |
| /* JAR_FILE */ |
| |
| /* various linked lists */ |
| ZZList *manifest; /* Digests of MF sections */ |
| ZZList *hashes; /* Digests of actual signed files */ |
| ZZList *phy; /* Physical layout of JAR file */ |
| ZZList *metainfo; /* Global metainfo */ |
| |
| JAR_Digest *globalmeta; /* digest of .MF global portion */ |
| |
| /* Below will change to a linked list to support multiple sigs */ |
| int pkcs7; /* Enforced opaqueness */ |
| int valid; /* PKCS7 signature validated */ |
| |
| ZZList *signers; /* the above, per signer */ |
| |
| /* Window context, very necessary for PKCS11 now */ |
| void *mw; /* MWContext window context */ |
| |
| /* Signal callback function */ |
| jar_settable_callback_fn *signal; |
| } JAR; |
| |
| /* |
| * Iterator |
| * |
| * Context for iterative operations. Certain operations |
| * require iterating multiple linked lists because of |
| * multiple signers. "nextsign" is used for this purpose. |
| * |
| */ |
| typedef struct JAR_Context_ { |
| JAR *jar; /* Jar we are searching */ |
| char *pattern; /* Regular expression */ |
| jarType finding; /* Type of item to find */ |
| ZZLink *next; /* Next item in find */ |
| ZZLink *nextsign; /* Next signer, sometimes */ |
| } JAR_Context; |
| |
| typedef struct JAR_Signer_ { |
| int pkcs7; /* Enforced opaqueness */ |
| int valid; /* PKCS7 signature validated */ |
| char *owner; /* name of .RSA file */ |
| JAR_Digest *digest; /* of .SF file */ |
| ZZList *sf; /* Linked list of .SF file contents */ |
| ZZList *certs; /* Signing information */ |
| } JAR_Signer; |
| |
| /* Meta informaton, or "policy", from the manifest file. |
| Right now just one tuple per JAR_Item. */ |
| typedef struct JAR_Metainfo_ { |
| char *header; |
| char *info; |
| } JAR_Metainfo; |
| |
| /* This should not be global */ |
| typedef struct JAR_Physical_ { |
| unsigned char compression; |
| unsigned long offset; |
| unsigned long length; |
| unsigned long uncompressed_length; |
| #if defined(XP_UNIX) || defined(XP_BEOS) |
| PRUint16 mode; |
| #endif |
| } JAR_Physical; |
| |
| typedef struct JAR_Cert_ { |
| size_t length; |
| void *key; |
| CERTCertificate *cert; |
| } JAR_Cert; |
| |
| /* certificate stuff */ |
| typedef enum { |
| jarCertCompany = 1, |
| jarCertCA = 2, |
| jarCertSerial = 3, |
| jarCertExpires = 4, |
| jarCertNickname = 5, |
| jarCertFinger = 6, |
| jarCertJavaHack = 100 |
| } jarCert; |
| |
| /* callback types */ |
| #define JAR_CB_SIGNAL 1 |
| |
| /* |
| * This is the base for the JAR error codes. It will |
| * change when these are incorporated into allxpstr.c, |
| * but right now they won't let me put them there. |
| * |
| */ |
| #ifndef SEC_ERR_BASE |
| #define SEC_ERR_BASE (-0x2000) |
| #endif |
| |
| #define JAR_BASE SEC_ERR_BASE + 300 |
| |
| /* Jar specific error definitions */ |
| |
| #define JAR_ERR_GENERAL (JAR_BASE + 1) |
| #define JAR_ERR_FNF (JAR_BASE + 2) |
| #define JAR_ERR_CORRUPT (JAR_BASE + 3) |
| #define JAR_ERR_MEMORY (JAR_BASE + 4) |
| #define JAR_ERR_DISK (JAR_BASE + 5) |
| #define JAR_ERR_ORDER (JAR_BASE + 6) |
| #define JAR_ERR_SIG (JAR_BASE + 7) |
| #define JAR_ERR_METADATA (JAR_BASE + 8) |
| #define JAR_ERR_ENTRY (JAR_BASE + 9) |
| #define JAR_ERR_HASH (JAR_BASE + 10) |
| #define JAR_ERR_PK7 (JAR_BASE + 11) |
| #define JAR_ERR_PNF (JAR_BASE + 12) |
| |
| /* Function declarations */ |
| |
| extern JAR *JAR_new(void); |
| |
| extern void PR_CALLBACK JAR_destroy(JAR *jar); |
| |
| extern char *JAR_get_error(int status); |
| |
| extern int JAR_set_callback(int type, JAR *jar, jar_settable_callback_fn *fn); |
| |
| extern void |
| JAR_init_callbacks(char *(*string_cb)(int), |
| void *(*find_cx)(void), |
| void *(*init_cx)(void)); |
| |
| /* |
| * JAR_set_context |
| * |
| * PKCS11 may require a password to be entered by the user |
| * before any crypto routines may be called. This will require |
| * a window context if used from inside Mozilla. |
| * |
| * Call this routine with your context before calling |
| * verifying or signing. If you have no context, call with NULL |
| * and one will be chosen for you. |
| * |
| */ |
| int JAR_set_context(JAR *jar, void /*MWContext*/ *mw); |
| |
| /* |
| * Iterative operations |
| * |
| * JAR_find sets up for repeated calls with JAR_find_next. |
| * I never liked findfirst and findnext, this is nicer. |
| * |
| * Pattern contains a relative pathname to match inside the |
| * archive. It is currently assumed to be "*". |
| * |
| * To use: |
| * |
| * JAR_Item *item; |
| * JAR_find (jar, "*.class", jarTypeMF); |
| * while (JAR_find_next (jar, &item) >= 0) |
| * { do stuff } |
| * |
| */ |
| |
| /* Replacement functions with an external context */ |
| |
| extern JAR_Context *JAR_find(JAR *jar, char *pattern, jarType type); |
| |
| extern int JAR_find_next(JAR_Context *ctx, JAR_Item **it); |
| |
| extern void JAR_find_end(JAR_Context *ctx); |
| |
| /* |
| * Function to parse manifest file: |
| * |
| * Many signatures may be attached to a single filename located |
| * inside the zip file. We only support one. |
| * |
| * Several manifests may be included in the zip file. |
| * |
| * You must pass the MANIFEST.MF file before any .SF files. |
| * |
| * Right now this returns a big ole list, privately in the jar structure. |
| * If you need to traverse it, use JAR_find if possible. |
| * |
| * The path is needed to determine what type of binary signature is |
| * being passed, though it is technically not needed for manifest files. |
| * |
| * When parsing an ASCII file, null terminate the ASCII raw_manifest |
| * prior to sending it, and indicate a length of 0. For binary digital |
| * signatures only, indicate the true length of the signature. |
| * (This is legacy behavior.) |
| * |
| * You may free the manifest after parsing it. |
| * |
| */ |
| |
| extern int |
| JAR_parse_manifest(JAR *jar, char *raw_manifest, long length, const char *path, |
| const char *url); |
| |
| /* |
| * Verify data (nonstreaming). The signature is actually |
| * checked by JAR_parse_manifest or JAR_pass_archive. |
| * |
| */ |
| |
| extern JAR_Digest *PR_CALLBACK |
| JAR_calculate_digest(void *data, long length); |
| |
| extern int PR_CALLBACK |
| JAR_verify_digest(JAR *jar, const char *name, JAR_Digest *dig); |
| |
| extern int |
| JAR_digest_file(char *filename, JAR_Digest *dig); |
| |
| /* |
| * Meta information |
| * |
| * Currently, since this call does not support passing of an owner |
| * (certificate, or physical name of the .sf file), it is restricted to |
| * returning information located in the manifest.mf file. |
| * |
| * Meta information is a name/value pair inside the archive file. Here, |
| * the name is passed in *header and value returned in **info. |
| * |
| * Pass a NULL as the name to retrieve metainfo from the global section. |
| * |
| * Data is returned in **info, of size *length. The return value |
| * will indicate if no data was found. |
| * |
| */ |
| |
| extern int |
| JAR_get_metainfo(JAR *jar, char *name, char *header, void **info, |
| unsigned long *length); |
| |
| extern char *JAR_get_filename(JAR *jar); |
| |
| extern char *JAR_get_url(JAR *jar); |
| |
| /* save the certificate with this fingerprint in persistent |
| storage, somewhere, for retrieval in a future session when there |
| is no corresponding JAR structure. */ |
| extern int PR_CALLBACK |
| JAR_stash_cert(JAR *jar, long keylen, void *key); |
| |
| /* retrieve a certificate presumably stashed with the above |
| function, but may be any certificate. Type is &CERTCertificate */ |
| CERTCertificate * |
| JAR_fetch_cert(long length, void *key); |
| |
| /* |
| * New functions to handle archives alone |
| * (call JAR_new beforehand) |
| * |
| * JAR_pass_archive acts much like parse_manifest. Certificates |
| * are returned in the JAR structure but as opaque data. When calling |
| * JAR_verified_extract you still need to decide which of these |
| * certificates to honor. |
| * |
| * Code to examine a JAR structure is in jarbert.c. You can obtain both |
| * a list of filenames and certificates from traversing the linked list. |
| * |
| */ |
| extern int |
| JAR_pass_archive(JAR *jar, jarArch format, char *filename, const char *url); |
| |
| /* |
| * Same thing, but don't check signatures |
| */ |
| extern int |
| JAR_pass_archive_unverified(JAR *jar, jarArch format, char *filename, |
| const char *url); |
| |
| /* |
| * Extracts a relative pathname from the archive and places it |
| * in the filename specified. |
| * |
| * Call JAR_set_nailed if you want to keep the file descriptors |
| * open between multiple calls to JAR_verify_extract. |
| * |
| */ |
| extern int |
| JAR_verified_extract(JAR *jar, char *path, char *outpath); |
| |
| /* |
| * JAR_extract does no crypto checking. This can be used if you |
| * need to extract a manifest file or signature, etc. |
| * |
| */ |
| extern int |
| JAR_extract(JAR *jar, char *path, char *outpath); |
| |
| #endif /* __JAR_h_ */ |