Back to index

lightning-sunbird  0.9+nobinonly
dbinit.c
Go to the documentation of this file.
00001 /*
00002  * NSS utility functions
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is the Netscape security libraries.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 /* $Id: dbinit.c,v 1.28.2.1 2006/09/22 00:21:03 julien.pierre.bugs%sun.com Exp $ */
00040 
00041 #include <ctype.h>
00042 #include "seccomon.h"
00043 #include "prinit.h"
00044 #include "prprf.h"
00045 #include "prmem.h"
00046 #include "pratom.h"
00047 #include "pcertt.h"
00048 #include "lowkeyi.h"
00049 #include "pcert.h"
00050 #include "cdbhdl.h"
00051 #include "keydbi.h"
00052 #include "pkcs11i.h"
00053 
00054 static char *
00055 sftk_certdb_name_cb(void *arg, int dbVersion)
00056 {
00057     const char *configdir = (const char *)arg;
00058     const char *dbver;
00059     char *smpname = NULL;
00060     char *dbname = NULL;
00061 
00062     switch (dbVersion) {
00063       case 8:
00064        dbver = "8";
00065        break;
00066       case 7:
00067        dbver = "7";
00068        break;
00069       case 6:
00070        dbver = "6";
00071        break;
00072       case 5:
00073        dbver = "5";
00074        break;
00075       case 4:
00076       default:
00077        dbver = "";
00078        break;
00079     }
00080 
00081     /* make sure we return something allocated with PORT_ so we have properly
00082      * matched frees at the end */
00083     smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
00084     if (smpname) {
00085        dbname = PORT_Strdup(smpname);
00086        PR_smprintf_free(smpname);
00087     }
00088     return dbname;
00089 }
00090     
00091 static char *
00092 sftk_keydb_name_cb(void *arg, int dbVersion)
00093 {
00094     const char *configdir = (const char *)arg;
00095     const char *dbver;
00096     char *smpname = NULL;
00097     char *dbname = NULL;
00098     
00099     switch (dbVersion) {
00100       case 4:
00101        dbver = "4";
00102        break;
00103       case 3:
00104        dbver = "3";
00105        break;
00106       case 1:
00107        dbver = "1";
00108        break;
00109       case 2:
00110       default:
00111        dbver = "";
00112        break;
00113     }
00114 
00115     smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
00116     if (smpname) {
00117        dbname = PORT_Strdup(smpname);
00118        PR_smprintf_free(smpname);
00119     }
00120     return dbname;
00121 }
00122 
00123 const char *
00124 sftk_EvaluateConfigDir(const char *configdir,char **appName)
00125 {
00126     if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
00127        char *cdir;
00128 
00129        *appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
00130        if (*appName == NULL) {
00131            return configdir;
00132        }
00133        cdir = *appName;
00134        while (*cdir && *cdir != ':') {
00135            cdir++;
00136        }
00137        if (*cdir == ':') {
00138           *cdir = 0;
00139           cdir++;
00140        }
00141        configdir = cdir;
00142     }
00143     return configdir;
00144 }
00145 
00146 static CK_RV
00147 sftk_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
00148                                        NSSLOWCERTCertDBHandle **certdbPtr)
00149 {
00150     NSSLOWCERTCertDBHandle *certdb = NULL;
00151     CK_RV        crv = CKR_NETSCAPE_CERTDB_FAILED;
00152     SECStatus    rv;
00153     char * name = NULL;
00154     char * appName = NULL;
00155 
00156     if (prefix == NULL) {
00157        prefix = "";
00158     }
00159 
00160     configdir = sftk_EvaluateConfigDir(configdir, &appName);
00161 
00162     name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
00163     if (name == NULL) goto loser;
00164 
00165     certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
00166     if (certdb == NULL) 
00167        goto loser;
00168 
00169     certdb->ref = 1;
00170 /* fix when we get the DB in */
00171     rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
00172                             sftk_certdb_name_cb, (void *)name, PR_FALSE);
00173     if (rv == SECSuccess) {
00174        crv = CKR_OK;
00175        *certdbPtr = certdb;
00176        certdb = NULL;
00177     }
00178 loser: 
00179     if (certdb) PR_Free(certdb);
00180     if (name) PR_smprintf_free(name);
00181     if (appName) PORT_Free(appName);
00182     return crv;
00183 }
00184 
00185 static CK_RV
00186 sftk_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
00187                                           NSSLOWKEYDBHandle **keydbPtr)
00188 {
00189     NSSLOWKEYDBHandle *keydb;
00190     char * name = NULL;
00191     char * appName = NULL;
00192 
00193     if (prefix == NULL) {
00194        prefix = "";
00195     }
00196     configdir = sftk_EvaluateConfigDir(configdir, &appName);
00197 
00198     name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);    
00199     if (name == NULL) 
00200        return CKR_HOST_MEMORY;
00201     keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix, 
00202                                    sftk_keydb_name_cb, (void *)name);
00203     PR_smprintf_free(name);
00204     if (appName) PORT_Free(appName);
00205     if (keydb == NULL)
00206        return CKR_NETSCAPE_KEYDB_FAILED;
00207     *keydbPtr = keydb;
00208 
00209     return CKR_OK;
00210 }
00211 
00212 
00213 /*
00214  * OK there are now lots of options here, lets go through them all:
00215  *
00216  * configdir - base directory where all the cert, key, and module datbases live.
00217  * certPrefix - prefix added to the beginning of the cert database example: "
00218  *                   "https-server1-"
00219  * keyPrefix - prefix added to the beginning of the key database example: "
00220  *                   "https-server1-"
00221  * secmodName - name of the security module database (usually "secmod.db").
00222  * readOnly - Boolean: true if the databases are to be openned read only.
00223  * nocertdb - Don't open the cert DB and key DB's, just initialize the 
00224  *                   Volatile certdb.
00225  * nomoddb - Don't open the security module DB, just initialize the 
00226  *                   PKCS #11 module.
00227  * forceOpen - Continue to force initializations even if the databases cannot
00228  *                   be opened.
00229  */
00230 CK_RV
00231 sftk_DBInit(const char *configdir, const char *certPrefix, 
00232            const char *keyPrefix, PRBool readOnly, 
00233            PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen,
00234            NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr)
00235 {
00236     CK_RV crv = CKR_OK;
00237 
00238 
00239     if (!noCertDB) {
00240        crv = sftk_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr);
00241        if (crv != CKR_OK) {
00242            if (!forceOpen) goto loser;
00243            crv = CKR_OK;
00244        }
00245     }
00246     if (!noKeyDB) {
00247 
00248        crv = sftk_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr);
00249        if (crv != CKR_OK) {
00250            if (!forceOpen) goto loser;
00251            crv = CKR_OK;
00252        }
00253     }
00254 
00255 
00256 loser:
00257     return crv;
00258 }
00259 
00260 NSSLOWCERTCertDBHandle *
00261 sftk_getCertDB(SFTKSlot *slot)
00262 {
00263     NSSLOWCERTCertDBHandle *certHandle;
00264 
00265     PZ_Lock(slot->slotLock);
00266     certHandle = slot->certDB;
00267     if (certHandle) {
00268        PR_AtomicIncrement(&certHandle->ref);
00269     }
00270     PZ_Unlock(slot->slotLock);
00271     return certHandle;
00272 }
00273 
00274 NSSLOWKEYDBHandle *
00275 sftk_getKeyDB(SFTKSlot *slot)
00276 {
00277     NSSLOWKEYDBHandle *keyHandle;
00278 
00279     PZ_Lock(slot->slotLock);
00280     keyHandle = slot->keyDB;
00281     if (keyHandle) {
00282        PR_AtomicIncrement(&keyHandle->ref);
00283     }
00284     PZ_Unlock(slot->slotLock);
00285     return keyHandle;
00286 }
00287 
00288 void
00289 sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle)
00290 {
00291    PRInt32 ref = PR_AtomicDecrement(&certHandle->ref);
00292    if (ref == 0) {
00293        nsslowcert_ClosePermCertDB(certHandle);
00294        PORT_Free(certHandle);
00295    }
00296 }
00297 
00298 void
00299 sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle)
00300 {
00301    PRInt32 ref = PR_AtomicDecrement(&keyHandle->ref);
00302    if (ref == 0) {
00303        nsslowkey_CloseKeyDB(keyHandle);
00304    }
00305 }
00306    
00307 
00308 static int rdbmapflags(int flags);
00309 static rdbfunc sftk_rdbfunc = NULL;
00310 static rdbstatusfunc sftk_rdbstatusfunc = NULL;
00311 
00312 /* NOTE: SHLIB_SUFFIX is defined on the command line */
00313 #define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
00314 
00315 DB * rdbopen(const char *appName, const char *prefix, 
00316                      const char *type, int flags, int *status)
00317 {
00318     PRLibrary *lib;
00319     DB *db;
00320 
00321     if (sftk_rdbfunc) {
00322        db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
00323        if (!db && status && sftk_rdbstatusfunc) {
00324            *status = (*sftk_rdbstatusfunc)();
00325        }
00326        return db;
00327     }
00328 
00329     /*
00330      * try to open the library.
00331      */
00332     lib = PR_LoadLibrary(RDBLIB);
00333 
00334     if (!lib) {
00335        return NULL;
00336     }
00337 
00338     /* get the entry points */
00339     sftk_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
00340     sftk_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
00341     if (sftk_rdbfunc) {
00342        db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
00343        if (!db && status && sftk_rdbstatusfunc) {
00344            *status = (*sftk_rdbstatusfunc)();
00345        }
00346        return db;
00347     }
00348 
00349     /* couldn't find the entry point, unload the library and fail */
00350     PR_UnloadLibrary(lib);
00351     return NULL;
00352 }
00353 
00354 /*
00355  * the following data structures are from rdb.h.
00356  */
00357 struct RDBStr {
00358     DB db;
00359     int (*xactstart)(DB *db);
00360     int (*xactdone)(DB *db, PRBool abort);
00361     int version;
00362     int (*dbinitcomplete)(DB *db);
00363 };
00364 
00365 #define DB_RDB ((DBTYPE) 0xff)
00366 #define RDB_RDONLY   1
00367 #define RDB_RDWR     2
00368 #define RDB_CREATE      4
00369 
00370 static int
00371 rdbmapflags(int flags) {
00372    switch (flags) {
00373    case NO_RDONLY:
00374        return RDB_RDONLY;
00375    case NO_RDWR:
00376        return RDB_RDWR;
00377    case NO_CREATE:
00378        return RDB_CREATE;
00379    default:
00380        break;
00381    }
00382    return 0;
00383 }
00384 
00385 
00386 PRBool
00387 db_IsRDB(DB *db)
00388 {
00389     return (PRBool) db->type == DB_RDB;
00390 }
00391 
00392 int
00393 db_BeginTransaction(DB *db)
00394 {
00395     struct RDBStr *rdb = (struct RDBStr *)db;
00396     if (db->type != DB_RDB) {
00397        return 0;
00398     }
00399 
00400     return rdb->xactstart(db);
00401 }
00402 
00403 int
00404 db_FinishTransaction(DB *db, PRBool abort)
00405 {
00406     struct RDBStr *rdb = (struct RDBStr *)db;
00407     if (db->type != DB_RDB) {
00408        return 0;
00409     }
00410 
00411     return rdb->xactdone(db, abort);
00412 }
00413 
00414 int
00415 db_InitComplete(DB *db)
00416 {
00417     struct RDBStr *rdb = (struct RDBStr *)db;
00418     if (db->type != DB_RDB) {
00419        return 0;
00420     }
00421     /* we should have addes a version number to the RDBS structure. Since we
00422      * didn't, we detect that we have and 'extended' structure if the rdbstatus
00423      * func exists */
00424     if (!sftk_rdbstatusfunc) {
00425        return 0;
00426     }
00427 
00428     return rdb->dbinitcomplete(db);
00429 }
00430 
00431 
00432 
00433 SECStatus
00434 db_Copy(DB *dest,DB *src)
00435 {
00436     int ret;
00437     DBT key,data;
00438     ret = (*src->seq)(src, &key, &data, R_FIRST);
00439     if (ret)  {
00440        return SECSuccess;
00441     }
00442 
00443     do {
00444        (void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE);
00445     } while ( (*src->seq)(src, &key, &data, R_NEXT) == 0);
00446     (void)(*dest->sync)(dest,0);
00447 
00448     return SECSuccess;
00449 }
00450