Back to index

lightning-sunbird  0.9+nobinonly
jarjart.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  *  JARJART
00039  *
00040  *  JAR functions used by Jartool
00041  */
00042 
00043 /* This allows manifest files above 64k to be
00044    processed on non-win16 platforms */
00045 
00046 #include "jar.h"
00047 #include "jarint.h"
00048 #include "jarjart.h"
00049 #include "blapi.h"   /* JAR is supposed to be above the line!! */
00050 #include "pk11func.h"       /* PK11 wrapper funcs are all above the line. */
00051 #include "certdb.h"
00052 
00053 /* from certdb.h */
00054 #define CERTDB_USER (1<<6)
00055 
00056 /*
00057  *  S O B _ l i s t _ c e r t s
00058  *
00059  *  Return a list of newline separated certificate nicknames
00060  *  (this function used by the Jartool)
00061  * 
00062  */
00063 
00064 static SECStatus jar_list_cert_callback 
00065      (CERTCertificate *cert, SECItem *k, void *data)
00066   {
00067   char *name;
00068   char **ugly_list;
00069 
00070   int trusted;
00071 
00072   ugly_list = (char **) data;
00073 
00074   if (cert)
00075     {
00076     name = cert->nickname;
00077 
00078     trusted = cert->trust->objectSigningFlags & CERTDB_USER;
00079 
00080     /* Add this name or email to list */
00081 
00082     if (name && trusted)
00083       {
00084       *ugly_list = (char*)PORT_Realloc
00085            (*ugly_list, PORT_Strlen (*ugly_list) + PORT_Strlen (name) + 2);
00086 
00087       if (*ugly_list)
00088         {
00089         if (**ugly_list)
00090           PORT_Strcat (*ugly_list, "\n");
00091 
00092         PORT_Strcat (*ugly_list, name);
00093         }
00094       }
00095     }
00096 
00097   return (SECSuccess);
00098   }
00099 
00100 /*
00101  *  S O B _ J A R _ l i s t _ c e r t s
00102  *
00103  *  Return a linfeed separated ascii list of certificate
00104  *  nicknames for the Jartool.
00105  *
00106  */
00107 
00108 char *JAR_JAR_list_certs (void)
00109   {
00110   SECStatus status = SECFailure;
00111   CERTCertDBHandle *certdb;
00112   CERTCertList *certs;
00113   CERTCertListNode *node;
00114 
00115   char *ugly_list;
00116 
00117   certdb = JAR_open_database();
00118 
00119   /* a little something */
00120   ugly_list = (char*)PORT_ZAlloc (16);
00121 
00122   if (ugly_list)
00123     {
00124     *ugly_list = 0;
00125 
00126     certs = PK11_ListCerts(PK11CertListUnique, NULL/* pwarg*/);
00127     if (certs)
00128       {
00129        for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
00130                             node = CERT_LIST_NEXT(node))
00131            {
00132            jar_list_cert_callback(node->cert, NULL, (void *)&ugly_list);
00133           }
00134        CERT_DestroyCertList(certs);
00135        status = SECSuccess;
00136        }
00137     }
00138 
00139   JAR_close_database (certdb);
00140 
00141   return (status != SECSuccess) ? NULL : ugly_list;
00142   }
00143 
00144 int JAR_JAR_validate_archive (char *filename)
00145   {
00146   JAR *jar;
00147   int status = -1;
00148 
00149   jar = JAR_new();
00150 
00151   if (jar)
00152     {
00153     status = JAR_pass_archive (jar, jarArchGuess, filename, "");
00154 
00155     if (status == 0)
00156       status = jar->valid;
00157 
00158     JAR_destroy (jar);
00159     }
00160 
00161   return status;
00162   }
00163 
00164 char *JAR_JAR_get_error (int status)
00165   {
00166   return JAR_get_error (status);
00167   }
00168 
00169 /*
00170  *  S O B _ J A R _  h a s h
00171  *
00172  *  Hash algorithm interface for use by the Jartool. Since we really
00173  *  don't know the private sizes of the context, and Java does need to
00174  *  know this number, allocate 512 bytes for it.
00175  *
00176  *  In april 1997 hashes in this file were changed to call PKCS11,
00177  *  as FIPS requires that when a smartcard has failed validation, 
00178  *  hashes are not to be performed. But because of the difficulty of
00179  *  preserving pointer context between calls to the JAR_JAR hashing
00180  *  functions, the hash routines are called directly, though after
00181  *  checking to see if hashing is allowed.
00182  *
00183  */
00184 
00185 void *JAR_JAR_new_hash (int alg)
00186   {
00187   void *context;
00188 
00189   MD5Context *md5;
00190   SHA1Context *sha1;
00191 
00192   /* this is a hack because this whole PORT_ZAlloc stuff looks scary */
00193 
00194   if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1))
00195     return NULL;
00196 
00197   context = PORT_ZAlloc (512);
00198 
00199   if (context)
00200     {
00201     switch (alg)
00202       {
00203       case 1:  /* MD5 */
00204                md5 = (MD5Context *) context;
00205                MD5_Begin (md5);
00206                break;
00207 
00208       case 2:  /* SHA1 */
00209                sha1 = (SHA1Context *) context;
00210                SHA1_Begin (sha1);
00211                break;
00212       }
00213     }
00214 
00215   return context;
00216   }
00217 
00218 void *JAR_JAR_hash (int alg, void *cookie, int length, void *data)
00219   {
00220   MD5Context *md5;
00221   SHA1Context *sha1;
00222 
00223   /* this is a hack because this whole PORT_ZAlloc stuff looks scary */
00224 
00225   if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1))
00226     return NULL;
00227 
00228   if (length > 0)
00229     {
00230     switch (alg)
00231       {
00232       case 1:  /* MD5 */
00233                md5 = (MD5Context *) cookie;
00234                MD5_Update (md5, (unsigned char*)data, length);
00235                break;
00236 
00237       case 2:  /* SHA1 */
00238                sha1 = (SHA1Context *) cookie;
00239                SHA1_Update (sha1, (unsigned char*)data, length);
00240                break;
00241       }
00242     }
00243 
00244   return cookie;
00245   }
00246 
00247 void *JAR_JAR_end_hash (int alg, void *cookie)
00248   {
00249   int length;
00250   unsigned char *data;
00251   char *ascii; 
00252 
00253   MD5Context *md5;
00254   SHA1Context *sha1;
00255 
00256   unsigned int md5_length;
00257   unsigned char md5_digest [MD5_LENGTH];
00258 
00259   unsigned int sha1_length;
00260   unsigned char sha1_digest [SHA1_LENGTH];
00261 
00262   /* this is a hack because this whole PORT_ZAlloc stuff looks scary */
00263 
00264   if (!PK11_HashOK (alg == 1 ? SEC_OID_MD5 : SEC_OID_SHA1)) 
00265     return NULL;
00266 
00267   switch (alg)
00268     {
00269     case 1:  /* MD5 */
00270 
00271              md5 = (MD5Context *) cookie;
00272 
00273              MD5_End (md5, md5_digest, &md5_length, MD5_LENGTH);
00274              /* MD5_DestroyContext (md5, PR_TRUE); */
00275 
00276              data = md5_digest;
00277              length = md5_length;
00278 
00279              break;
00280 
00281     case 2:  /* SHA1 */
00282 
00283              sha1 = (SHA1Context *) cookie;
00284 
00285              SHA1_End (sha1, sha1_digest, &sha1_length, SHA1_LENGTH);
00286              /* SHA1_DestroyContext (sha1, PR_TRUE); */
00287 
00288              data = sha1_digest;
00289              length = sha1_length;
00290 
00291              break;
00292 
00293     default: return NULL;
00294     }
00295 
00296   /* Instead of destroy context, since we created it */
00297   /* PORT_Free (cookie); */
00298 
00299   ascii = BTOA_DataToAscii(data, length);
00300 
00301   return ascii ? PORT_Strdup (ascii) : NULL;
00302   }
00303 
00304 /*
00305  *  S O B _ J A R _ s i g n _ a r c h i v e
00306  *
00307  *  A simple API to sign a JAR archive.
00308  *
00309  */
00310 
00311 int JAR_JAR_sign_archive 
00312       (char *nickname, char *password, char *sf, char *outsig)
00313   {
00314   char *out_fn;
00315 
00316   int status = JAR_ERR_GENERAL;
00317   JAR_FILE sf_fp; 
00318   JAR_FILE out_fp;
00319 
00320   CERTCertDBHandle *certdb;
00321   void *keydb;
00322 
00323   CERTCertificate *cert;
00324 
00325   /* open cert and key databases */
00326 
00327   certdb = JAR_open_database();
00328   if (certdb == NULL)
00329     return JAR_ERR_GENERAL;
00330 
00331   keydb = jar_open_key_database();
00332   if (keydb == NULL)
00333     return JAR_ERR_GENERAL;
00334 
00335   out_fn = PORT_Strdup (sf);
00336 
00337   if (out_fn == NULL || PORT_Strlen (sf) < 5)
00338     return JAR_ERR_GENERAL;
00339 
00340   sf_fp = JAR_FOPEN (sf, "rb");
00341   out_fp = JAR_FOPEN (outsig, "wb");
00342 
00343   cert = CERT_FindCertByNickname (certdb, nickname);
00344 
00345   if (cert && sf_fp && out_fp)
00346     {
00347     status = jar_create_pk7 (certdb, keydb, cert, password, sf_fp, out_fp);
00348     }
00349 
00350   /* remove password from prying eyes */
00351   PORT_Memset (password, 0, PORT_Strlen (password));
00352 
00353   JAR_FCLOSE (sf_fp);
00354   JAR_FCLOSE (out_fp);
00355 
00356   JAR_close_database (certdb);
00357   jar_close_key_database (keydb);
00358 
00359   return status;
00360   }