/* 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 /* 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) 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_ */