Compare commits
107 Commits
NSS_BOB_SH
...
CacheInteg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22c40d96b2 | ||
|
|
06a79b2069 | ||
|
|
ebc4face0d | ||
|
|
150696bb86 | ||
|
|
683045595b | ||
|
|
7f09538b93 | ||
|
|
bb364ef512 | ||
|
|
7c96c92a19 | ||
|
|
a6defdef4c | ||
|
|
76159a2caf | ||
|
|
1988cb05b5 | ||
|
|
dd8c6b3bed | ||
|
|
bc64749366 | ||
|
|
2e9287bd58 | ||
|
|
0f2274a140 | ||
|
|
957fa10cac | ||
|
|
e603146886 | ||
|
|
cb698a0df1 | ||
|
|
1b918d9ef0 | ||
|
|
6407144c9f | ||
|
|
2ed563a178 | ||
|
|
4becc0b508 | ||
|
|
7d5427ea31 | ||
|
|
99904bcc48 | ||
|
|
bcb56c9593 | ||
|
|
f18bc8e6cd | ||
|
|
7d14c5669a | ||
|
|
c0dd3df02e | ||
|
|
e5cc84978f | ||
|
|
5694537330 | ||
|
|
297c5ceba3 | ||
|
|
e0311312f7 | ||
|
|
cf3dc77b02 | ||
|
|
dd2506a737 | ||
|
|
b1bee1f21c | ||
|
|
48ecc5625b | ||
|
|
1b791685e6 | ||
|
|
dc94d1d6e2 | ||
|
|
f5b437ade3 | ||
|
|
8c0b4b3e4a | ||
|
|
fb640ab144 | ||
|
|
106e263b33 | ||
|
|
85045a8552 | ||
|
|
a2279be132 | ||
|
|
0ce702d402 | ||
|
|
f14d03cd67 | ||
|
|
b91343fdf6 | ||
|
|
2c517489b5 | ||
|
|
ae57da58eb | ||
|
|
8d4586dd65 | ||
|
|
9b473ad9be | ||
|
|
2ad227a994 | ||
|
|
94d8da33c1 | ||
|
|
81c05809fd | ||
|
|
e30547b2b2 | ||
|
|
257f9cfaaa | ||
|
|
96e2654e43 | ||
|
|
3b023433be | ||
|
|
1b89716afe | ||
|
|
ad02058877 | ||
|
|
fa8a3196e7 | ||
|
|
5c2c543e58 | ||
|
|
c588721cc0 | ||
|
|
0b049b17ba | ||
|
|
854ef4631d | ||
|
|
051c558653 | ||
|
|
37a04adb09 | ||
|
|
c823c04b45 | ||
|
|
03cbd000eb | ||
|
|
a91e91a1c7 | ||
|
|
be7a5a48b6 | ||
|
|
b2bc7468e8 | ||
|
|
9692dfd994 | ||
|
|
f3edd4cfb5 | ||
|
|
33403345c1 | ||
|
|
20c850de23 | ||
|
|
e8b619cd02 | ||
|
|
eed396bb92 | ||
|
|
41d44c070b | ||
|
|
698ba42268 | ||
|
|
1a0fd23991 | ||
|
|
67dded330b | ||
|
|
936ff4777a | ||
|
|
96c55e42f7 | ||
|
|
82fa0cf06a | ||
|
|
98c8285334 | ||
|
|
bad4b683f4 | ||
|
|
cb5269a28a | ||
|
|
74712f3635 | ||
|
|
9f8ea739db | ||
|
|
97a10dd7c6 | ||
|
|
85a132fac0 | ||
|
|
e594eee877 | ||
|
|
9148eee3d6 | ||
|
|
b5989a8382 | ||
|
|
2b861f60d9 | ||
|
|
87db050b37 | ||
|
|
ffe483cf95 | ||
|
|
52aa17a1c3 | ||
|
|
5fdb3aa69e | ||
|
|
8cae473bc0 | ||
|
|
0719303755 | ||
|
|
90d3e40858 | ||
|
|
c792b2d35c | ||
|
|
7a4377d840 | ||
|
|
a5fa416010 | ||
|
|
49d00db5e2 |
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
38
mozilla/netwerk/cache/Makefile.in
vendored
Normal file
38
mozilla/netwerk/cache/Makefile.in
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
public \
|
||||
memcache \
|
||||
filecache \
|
||||
mgr \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
|
||||
DEPTH=..\..
|
||||
DIRS= \
|
||||
public \
|
||||
mgr \
|
||||
memcache \
|
||||
filecache \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
54
mozilla/netwerk/cache/build/Makefile.in
vendored
Normal file
54
mozilla/netwerk/cache/build/Makefile.in
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcacke
|
||||
LIBRARY_NAME = necko_cache
|
||||
IS_COMPONENT = 1
|
||||
|
||||
CPPSRCS = nsNetDataCacheModule.cpp
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
$(DIST)/lib/libnkcachemgr_s.a \
|
||||
$(DIST)/lib/libnkfilecache_s.a \
|
||||
$(DIST)/lib/libnkmemcache_s.a \
|
||||
$(DIST)/lib/libmozdbm_s.a \
|
||||
$(DIST)/lib/libxpcomio_s.a \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(DEPTH)/netwerk/cache/memcache \
|
||||
-I$(DEPTH)/netwerk/cache/filecache \
|
||||
-I$(DEPTH)/netwerk/cache/mgr \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MKSHLIB_FORCE_ALL) \
|
||||
$(SHARED_LIBRARY_LIBS) \
|
||||
$(MKSHLIB_UNFORCE_ALL) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile
|
||||
|
||||
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=nkcache
|
||||
|
||||
MAKE_OBJ_TYPE=DLL
|
||||
DLLNAME=nkcache
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsNetDataCacheModule.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\nkcachemgr_s.lib \
|
||||
$(DIST)\lib\nkfilecache_s.lib \
|
||||
$(DIST)\lib\nkmemcache_s.lib \
|
||||
$(DIST)\lib\dbm32.lib \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\netwerk\cache\memcache \
|
||||
-I$(DEPTH)\netwerk\cache\filecache \
|
||||
-I$(DEPTH)\netwerk\cache\mgr \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
#include "nsMemCache.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCacheManager.h"
|
||||
|
||||
// Factory method to create a new nsMemCache instance. Used
|
||||
// by nsNetDataCacheModule
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
|
||||
|
||||
static nsModuleComponentInfo components[] = {
|
||||
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
|
||||
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
|
||||
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE("Network Data Cache", components)
|
||||
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is Mozilla Communicator.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Intel Corp.
|
||||
# Portions created by Intel Corp. are
|
||||
# Copyright (C) 1999, 1999 Intel Corp. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
# Carl Wong <carl.wong@intel.com>
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h \
|
||||
nsNetDiskCache.h \
|
||||
nsIDBAccessor.h \
|
||||
nsDBAccessor.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsDBAccessor.cpp\
|
||||
nsDBEnumerator.cpp \
|
||||
nsNetDiskCache.cpp \
|
||||
nsDiskCacheRecord.cpp \
|
||||
nsDiskCacheRecordChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsDBAccessor.obj \
|
||||
.\$(OBJDIR)\nsDBEnumerator.obj \
|
||||
.\$(OBJDIR)\nsNetDiskCache.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecordChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
* a nsDiskCacheRecord is mapped into two entries in the database,
|
||||
* key->recordID
|
||||
* recordID->metadata
|
||||
*/
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "plhash.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
nsDBAccessor::nsDBAccessor() :
|
||||
mDB(0) ,
|
||||
mDBFile(0) ,
|
||||
mSessionID(0) ,
|
||||
mSessionCntr(0) ,
|
||||
mDBFilesize(0)
|
||||
{
|
||||
mLastSyncTime = PR_IntervalNow() ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsDBAccessor::~nsDBAccessor()
|
||||
{
|
||||
Shutdown() ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// nsIDBAccessor methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Init(nsIFileSpec* dbfile)
|
||||
{
|
||||
char* dbname ;
|
||||
|
||||
// this should cover all platforms.
|
||||
dbfile->GetNativePath(&dbname) ;
|
||||
|
||||
mDBFile = dbfile ;
|
||||
|
||||
// FUR - how is page size chosen ? It's worth putting a comment
|
||||
// in here about the possible usefulness of tuning these parameters
|
||||
HASHINFO hash_info = {
|
||||
16*1024 , /* bucket size */
|
||||
0 , /* fill factor */
|
||||
0 , /* number of elements */
|
||||
0 , /* bytes to cache */
|
||||
0 , /* hash function */
|
||||
0} ; /* byte order */
|
||||
|
||||
mDB = dbopen(dbname,
|
||||
O_RDWR | O_CREAT ,
|
||||
0600 ,
|
||||
DB_HASH ,
|
||||
& hash_info) ;
|
||||
|
||||
nsCRT::free(dbname) ;
|
||||
|
||||
if(!mDB)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mSessionID
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
|
||||
db_key.size = PL_strlen(SessionKey) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get session id in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
// get the last session id
|
||||
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
|
||||
if(*old_ID < ini_sessionID) {
|
||||
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
mSessionID = *old_ID + 1 ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// must be a new db
|
||||
mSessionID = ini_sessionID ;
|
||||
}
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
|
||||
db_data.size = sizeof(PRInt16) ;
|
||||
|
||||
// store the new session id
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
|
||||
// initialize database filesize
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("reset session ID failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Shutdown(void)
|
||||
{
|
||||
if(mDB) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
(*mDB->close)(mDB) ;
|
||||
mDB = nsnull ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
int status = 0 ;
|
||||
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1)
|
||||
return NS_OK ;
|
||||
else
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It's more important to remove the id->metadata entry first since
|
||||
* key->id mapping is just a reference
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key ;
|
||||
|
||||
// delete recordID->metadata
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
PRInt32 status = -1 ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// delete key->recordID
|
||||
db_key.data = anEntry ;
|
||||
db_key.size = aLength ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
return Sync() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, key) ;
|
||||
db_key.size = length ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == 0) {
|
||||
// found recordID
|
||||
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// create a new one
|
||||
PRInt32 id = 0 ;
|
||||
id = mSessionID << 16 | mSessionCntr++ ;
|
||||
|
||||
// add new id into mDB
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
|
||||
db_data.size = sizeof(PRInt32) ;
|
||||
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status != 0) {
|
||||
NS_ERROR("updating db failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
*aID = id ;
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("ERROR: keydb failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
PRUint32 flag ;
|
||||
|
||||
if(bReset)
|
||||
flag = R_FIRST ;
|
||||
else
|
||||
flag = R_NEXT ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
PRUint32 len = PL_strlen(SessionKey) ;
|
||||
|
||||
int status ;
|
||||
|
||||
do {
|
||||
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
|
||||
flag = R_NEXT ;
|
||||
if(status == -1)
|
||||
return NS_ERROR_FAILURE ;
|
||||
// get next if it's a key->recordID
|
||||
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
|
||||
continue ;
|
||||
// get next if it's a sessionID entry
|
||||
if(db_key.size == len && db_data.size == sizeof(PRInt16))
|
||||
continue ;
|
||||
// recordID is always 32 bits long
|
||||
if(db_key.size == sizeof(PRInt32))
|
||||
break ;
|
||||
} while(!status) ;
|
||||
|
||||
if (0 == status) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the cached database file size.
|
||||
* mDBFilesize will be updated during Sync().
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetDBFilesize(PRUint32* aSize)
|
||||
{
|
||||
*aSize = mDBFilesize ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetSpecialEntry(void** anEntry, PRUint32* aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get special entry in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::SetSpecialEntry(void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sync routine is only called when the SyncInterval is reached. Otherwise
|
||||
* it just returns. If db synced, the filesize will be updated at the
|
||||
* same time.
|
||||
*/
|
||||
nsresult
|
||||
nsDBAccessor::Sync(void)
|
||||
{
|
||||
PRIntervalTime time = PR_IntervalNow() ;
|
||||
PRIntervalTime duration = time - mLastSyncTime ;
|
||||
|
||||
if (PR_IntervalToMilliseconds(duration) > SyncInterval) {
|
||||
int status = (*mDB->sync)(mDB, 0) ;
|
||||
if(status == 0) {
|
||||
// printf("\tsynced\n") ;
|
||||
mLastSyncTime = time ;
|
||||
|
||||
// update db filesize here
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
|
||||
} else
|
||||
return NS_ERROR_FAILURE ;
|
||||
} else {
|
||||
// printf("\tnot synced\n") ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NSIDBACCESSOR_H_
|
||||
#define _NSIDBACCESSOR_H_
|
||||
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "mcom_db.h"
|
||||
#include "prinrval.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// bogus string for the key of session id
|
||||
static const char * const SessionKey = "SK" ;
|
||||
|
||||
// bogus string for the size
|
||||
static const char * const SpecialEntry = "SE" ;
|
||||
|
||||
// initial session id number
|
||||
static const PRInt16 ini_sessionID = 0xff ;
|
||||
|
||||
static const PRUint16 SyncInterval = 1000 ;
|
||||
|
||||
class nsDBAccessor : public nsIDBAccessor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDBAccessor() ;
|
||||
virtual ~nsDBAccessor() ;
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
|
||||
NS_IMETHOD Shutdown(void) ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
protected:
|
||||
nsresult Sync(void) ;
|
||||
|
||||
private:
|
||||
DB * mDB ;
|
||||
nsCOMPtr<nsIFileSpec> mDBFile ;
|
||||
PRInt16 mSessionID ;
|
||||
PRInt16 mSessionCntr ;
|
||||
PRIntervalTime mLastSyncTime ;
|
||||
PRUint32 mDBFilesize ; // cached DB filesize,
|
||||
// updated on every sync for now
|
||||
} ;
|
||||
|
||||
#endif // _NSIDBACCESSOR_H_
|
||||
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#include "nsDBEnumerator.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
|
||||
m_DB(aDB) ,
|
||||
m_DiskCache(aCache) ,
|
||||
m_tempEntry(0) ,
|
||||
m_tempEntry_length(0) ,
|
||||
m_CacheEntry(0) ,
|
||||
m_bReset(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsDBEnumerator::~nsDBEnumerator()
|
||||
{
|
||||
NS_IF_RELEASE(m_CacheEntry) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// nsISimpleEnumerator methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::HasMoreElements(PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
nsresult rv = m_DB->EnumEntry(&m_tempEntry, &m_tempEntry_length, m_bReset) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// do some error recovery
|
||||
m_DiskCache->DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
m_bReset = PR_FALSE ;
|
||||
|
||||
if(m_tempEntry && m_tempEntry_length != 0)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine does not create a new item by itself
|
||||
// Rather it reuses the item inside the object. So if you need to use the
|
||||
// item later, you have to
|
||||
// create a new item specifically, using copy constructor or some other dup
|
||||
// function. And don't forget to release it after you're done
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::GetNext(nsISupports **_retval)
|
||||
{
|
||||
if(!m_CacheEntry) {
|
||||
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
|
||||
if(m_CacheEntry)
|
||||
NS_ADDREF(m_CacheEntry) ;
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv = m_CacheEntry->RetrieveInfo(m_tempEntry, m_tempEntry_length) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
|
||||
NS_ADDREF(*_retval) ; // all good getter addref
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#ifndef _NS_DBENUMERATOR_H_
|
||||
#define _NS_DBENUMERATOR_H_
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
class nsCachedDiskData ; /* forward decl */
|
||||
|
||||
class nsDBEnumerator : public nsISimpleEnumerator {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDBEnumerator() ;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDBAccessor> m_DB ;
|
||||
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
|
||||
void * m_tempEntry ;
|
||||
PRUint32 m_tempEntry_length ;
|
||||
nsDiskCacheRecord* m_CacheEntry ;
|
||||
PRBool m_bReset ;
|
||||
};
|
||||
|
||||
#endif // _NS_DBENUMERATOR_H_
|
||||
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsFileStream.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIAllocator.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "prtypes.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
|
||||
mKey(0) ,
|
||||
mKeyLength(0) ,
|
||||
mRecordID(0) ,
|
||||
mMetaData(0) ,
|
||||
mMetaDataLength(0) ,
|
||||
mDB(db) ,
|
||||
mInfo(0) ,
|
||||
mInfoSize(0) ,
|
||||
mNumChannels(0) ,
|
||||
mDiskCache(aCache)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ASSERTION(mDiskCache, "Must have an nsNetDiskCache");
|
||||
NS_ADDREF(mDiskCache);
|
||||
}
|
||||
|
||||
// mem alloced. so caller should do free() on key.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Init(const char* key, PRUint32 length, PRInt32 ID)
|
||||
{
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
// copy key
|
||||
mKeyLength = length ;
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, key, length) ;
|
||||
|
||||
// get RecordID
|
||||
mRecordID = ID ;
|
||||
|
||||
// setup the file name
|
||||
nsCOMPtr<nsIFileSpec> dbFolder ;
|
||||
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
|
||||
|
||||
nsresult rv = mFile->FromFileSpec(dbFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// dir is a hash result of mRecordID%32, hope it's enough
|
||||
char filename[9], dirName[3] ;
|
||||
|
||||
PR_snprintf(dirName, 3, "%02x", (((PRUint32)mRecordID) % 32)) ;
|
||||
mFile->AppendRelativeUnixPath(dirName) ;
|
||||
|
||||
PR_snprintf(filename, 9, "%08x", mRecordID) ;
|
||||
mFile->AppendRelativeUnixPath(filename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecord::~nsDiskCacheRecord()
|
||||
{
|
||||
if(mKey)
|
||||
nsAllocator::Free(mKey) ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
NS_IF_RELEASE(mDiskCache);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCacheRecord methods
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*length = mKeyLength ;
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mKey, mKeyLength) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
|
||||
{
|
||||
*aRecordID = mRecordID ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
// always null the return value first.
|
||||
*_retval = nsnull ;
|
||||
|
||||
*length = mMetaDataLength ;
|
||||
|
||||
if(mMetaDataLength) {
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mMetaData, mMetaDataLength) ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
|
||||
{
|
||||
// set the mMetaData
|
||||
mMetaDataLength = length ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
memcpy(mMetaData, data, length) ;
|
||||
|
||||
// Generate mInfo
|
||||
nsresult rv = GenInfo() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// write through into mDB
|
||||
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
return mFile->GetFileSize(aStoredContentLength) ;
|
||||
}
|
||||
|
||||
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 len = 0 ;
|
||||
nsresult rv = mFile->GetFileSize(&len) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(len < aStoredContentLength)
|
||||
{
|
||||
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
else {
|
||||
rv = mFile->Truncate(aStoredContentLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
mDiskCache->m_StorageInUse -= (len - aStoredContentLength) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Delete(void)
|
||||
{
|
||||
if(mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE ;
|
||||
|
||||
PRUint32 len ;
|
||||
mFile->GetFileSize(&len) ;
|
||||
|
||||
nsFileSpec cache_file ;
|
||||
nsresult rv = mFile->GetFileSpec(&cache_file) ;
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
cache_file.Delete(PR_TRUE) ;
|
||||
|
||||
// updata the storage size
|
||||
mDiskCache->m_StorageInUse -= len ;
|
||||
|
||||
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
else
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
|
||||
{
|
||||
if(!aFilename)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aFilename = mFile ;
|
||||
NS_ADDREF(*aFilename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
|
||||
{
|
||||
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
|
||||
if(!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
nsresult rv = channel->Init() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
NS_ADDREF(channel) ;
|
||||
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsDiskCacheRecord methods
|
||||
|
||||
// file name is represented by a url string. I hope this would be more
|
||||
// generic
|
||||
nsresult
|
||||
nsDiskCacheRecord::GenInfo()
|
||||
{
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
char* file_url=nsnull ;
|
||||
PRUint32 name_len ;
|
||||
mFile->GetURLString(&file_url) ;
|
||||
name_len = PL_strlen(file_url)+1 ;
|
||||
|
||||
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
|
||||
mInfoSize += sizeof(PRInt32) ; // RecordID
|
||||
mInfoSize += sizeof(PRUint32) ; // key length
|
||||
mInfoSize += mKeyLength ; // key
|
||||
mInfoSize += sizeof(PRUint32) ; // metadata length
|
||||
mInfoSize += mMetaDataLength ; // metadata
|
||||
mInfoSize += sizeof(PRUint32) ; // filename length
|
||||
mInfoSize += name_len ; // filename
|
||||
|
||||
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
|
||||
if(!newInfo) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// copy the checksum mInfoSize
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
|
||||
COPY_INT32(cur_ptr, &mInfoSize) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy RecordID
|
||||
COPY_INT32(cur_ptr, &mRecordID) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// copy key length
|
||||
COPY_INT32(cur_ptr, &mKeyLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy key
|
||||
memcpy(cur_ptr, mKey, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
// copy metadata length
|
||||
COPY_INT32(cur_ptr, &mMetaDataLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy metadata
|
||||
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// copy file name length
|
||||
COPY_INT32(cur_ptr, &name_len) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy file name
|
||||
memcpy(cur_ptr, file_url, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
|
||||
mInfo = newInfo ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Method suppose to get all the info from the db record
|
||||
* and set them to accroding members. the original values
|
||||
* will all be overwritten. only minimal error checking is performed.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
|
||||
{
|
||||
// reset everything
|
||||
if(mInfo) {
|
||||
nsAllocator::Free(mInfo) ;
|
||||
mInfo = nsnull ;
|
||||
}
|
||||
|
||||
if(mKey) {
|
||||
nsAllocator::Free(mKey) ;
|
||||
mKey = nsnull ;
|
||||
}
|
||||
if(mMetaData) {
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = nsnull ;
|
||||
}
|
||||
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
|
||||
|
||||
char* file_url ;
|
||||
PRUint32 name_len ;
|
||||
|
||||
// set mInfoSize
|
||||
COPY_INT32(&mInfoSize, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// check this at least
|
||||
if(mInfoSize != aInfoLength)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mRecordID
|
||||
COPY_INT32(&mRecordID, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// set mKeyLength
|
||||
COPY_INT32(&mKeyLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mKey
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, cur_ptr, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
PRInt32 id ;
|
||||
mDB->GetID(mKey, mKeyLength, &id) ;
|
||||
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
|
||||
|
||||
// set mMetaDataLength
|
||||
COPY_INT32(&mMetaDataLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mMetaData
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// get mFile name length
|
||||
COPY_INT32(&name_len, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get mFile native name
|
||||
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
|
||||
if(!file_url)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(file_url, cur_ptr, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
|
||||
|
||||
// create mFile if Init() isn't called
|
||||
if(!mFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// setup mFile
|
||||
mFile->SetURLString(file_url) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NET_CACHEDDISKDATA_H_
|
||||
#define _NET_CACHEDDISKDATA_H_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
|
||||
class nsDiskCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
|
||||
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDiskCacheRecord() ;
|
||||
|
||||
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
|
||||
NS_IMETHOD Init(const char* key, PRUint32 length, PRInt32 ID) ;
|
||||
|
||||
nsresult GenInfo(void) ;
|
||||
|
||||
private:
|
||||
|
||||
char* mKey ;
|
||||
PRUint32 mKeyLength ;
|
||||
PRInt32 mRecordID ;
|
||||
char* mMetaData ;
|
||||
PRUint32 mMetaDataLength ;
|
||||
nsCOMPtr<nsIFileSpec> mFile ;
|
||||
nsCOMPtr<nsIDBAccessor> mDB ;
|
||||
void* mInfo ;
|
||||
PRUint32 mInfoSize ;
|
||||
PRUint32 mNumChannels ;
|
||||
nsNetDiskCache* mDiskCache ;
|
||||
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
friend class nsNetDiskCache ;
|
||||
} ;
|
||||
|
||||
#endif // _NET_CACHEDDISKDATA_H_
|
||||
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Most of the code are taken from nsFileChannel.
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsIFileTransportService.h"
|
||||
//#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "netCore.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
|
||||
//static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
||||
|
||||
// This is copied from nsMemCacheChannel, We should consolidate these two.
|
||||
class WriteStreamWrapper : public nsIOutputStream
|
||||
{
|
||||
public:
|
||||
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream) ;
|
||||
|
||||
virtual ~WriteStreamWrapper() ;
|
||||
|
||||
static nsresult
|
||||
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBASESTREAM
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
|
||||
private:
|
||||
nsDiskCacheRecordChannel* mChannel;
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
} ;
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream)
|
||||
: mChannel(aChannel), mBaseStream(aBaseStream)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
WriteStreamWrapper::~WriteStreamWrapper()
|
||||
{
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
|
||||
{
|
||||
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
|
||||
{
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Flush()
|
||||
{
|
||||
return mBaseStream->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Close()
|
||||
{
|
||||
return mBaseStream->Close();
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
|
||||
nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord) ,
|
||||
mLoadGroup(aLoadGroup)
|
||||
{
|
||||
NS_INIT_REFCNT() ;
|
||||
NS_ADDREF(mRecord);
|
||||
mRecord->mNumChannels++ ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
|
||||
{
|
||||
mRecord->mNumChannels-- ;
|
||||
NS_RELEASE(mRecord);
|
||||
}
|
||||
|
||||
// I know that I gave conflicting advice on the issue of file
|
||||
// transport versus file protocol handler, but I thought that the
|
||||
// last word was that we would use the raw transport, when I wrote:
|
||||
//
|
||||
// > I just thought of an argument for the other side of the coin, i.e. the
|
||||
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
|
||||
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
|
||||
// > is brain-dead and scans every directory on the path to the file. It's
|
||||
// > cheaper to create a nsFileSpec for a cache file by combining a single,
|
||||
// > static nsFileSpec that corresponds to the cache directory with the
|
||||
// > relative path to the cache file (using nsFileSpec's operator +). This
|
||||
// > operation is optimized on the Mac to avoid the scanning operation.
|
||||
//
|
||||
// The Mac guys will eat us alive if we do path string to nsFileSpec
|
||||
// conversions for every cache file we open.
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::Init(void)
|
||||
{
|
||||
nsresult rv = mRecord->mFile->GetFileSpec(&mSpec) ;
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
||||
// Don't assume we actually created a good file spec
|
||||
FSSpec theSpec = mSpec.GetFSSpec();
|
||||
if (!theSpec.name[0]) {
|
||||
NS_ERROR("failed to create a file spec");
|
||||
|
||||
// Since we didn't actually create the file spec
|
||||
// we return an error
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
|
||||
}
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS4(nsDiskCacheRecordChannel,
|
||||
nsIChannel,
|
||||
nsIRequest,
|
||||
nsIStreamListener,
|
||||
nsIStreamObserver)
|
||||
|
||||
// implement nsIRequest
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE ;
|
||||
if(!mFileTransport)
|
||||
return NS_OK ;
|
||||
|
||||
return mFileTransport->IsPending(aIsPending) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Cancel(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Cancel() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Suspend(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Suspend() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Resume(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Resume() ;
|
||||
}
|
||||
|
||||
// implement nsIChannel
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
|
||||
{
|
||||
// FUR - might need to implement this - not sure
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->GetURI(aURI) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenInputStream(aStartPosition, aReadCount, aResult) ;
|
||||
if(NS_FAILED(rv))
|
||||
mFileTransport = nsnull ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
|
||||
nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
NS_ENSURE_ARG(aResult) ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
mFileTransport = nsnull ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
|
||||
nsISupports *ctxt)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsISupports *aContext,
|
||||
nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
mRealListener = aListener;
|
||||
nsCOMPtr<nsIStreamListener> tempListener = this;
|
||||
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory) {
|
||||
nsIStreamListener *newListener;
|
||||
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mRealListener = newListener;
|
||||
NS_RELEASE(newListener);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mLoadGroup->AddChannel(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// no callbacks
|
||||
|
||||
rv = mFileTransport->AsyncRead(aStartPosition,
|
||||
aReadCount,
|
||||
aContext,
|
||||
tempListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// release the transport so that we don't think we're in progress
|
||||
mFileTransport = nsnull;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
|
||||
PRUint32 startPosition,
|
||||
PRInt32 writeCount,
|
||||
nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
|
||||
{
|
||||
/*
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->AsyncWrite(fromStream,
|
||||
startPosition,
|
||||
writeCount,
|
||||
ctxt,
|
||||
observer) ;
|
||||
*/
|
||||
|
||||
// I can't do this since the write is not monitored, and I won't be
|
||||
// able to updata the storage.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#define DUMMY_TYPE "text/html"
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if (mSpec.IsDirectory()) {
|
||||
*aContentType = nsCRT::strdup("application/http-index-format");
|
||||
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
// I wish I can make this simplier
|
||||
|
||||
char* urlStr ;
|
||||
mRecord->mFile->GetURLString(&urlStr) ;
|
||||
|
||||
// file: URLs (currently) have no additional structure beyond that provided by standard
|
||||
// URLs, so there is no "outer" given to CreateInstance
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
|
||||
NS_GET_IID(nsIURI),
|
||||
//(void**)&url);
|
||||
getter_AddRefs(url)) ;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = url->SetSpec((char*)urlStr);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = MIMEService->GetTypeFromURI(url, aContentType);
|
||||
if (NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
// if all else fails treat it as text/html?
|
||||
*aContentType = nsCRT::strdup(DUMMY_TYPE);
|
||||
if (!*aContentType) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 length;
|
||||
|
||||
rv = mRecord->mFile->GetFileSize(&length);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aContentLength = (PRInt32)length;
|
||||
} else {
|
||||
*aContentLength = -1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get() ;
|
||||
NS_IF_ADDREF(*aOwner) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
mOwner = aOwner ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamListener methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
|
||||
{
|
||||
NS_ASSERTION(mRealListener, "No listener...");
|
||||
return mRealListener->OnStartRequest(this, context);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
|
||||
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Release the reference to the consumer stream listener...
|
||||
mRealListener = null_nsCOMPtr();
|
||||
mFileTransport = null_nsCOMPtr();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsIInputStream *aIStream, PRUint32 aSourceOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnDataAvailable(this, context, aIStream,
|
||||
aSourceOffset, aLength);
|
||||
|
||||
//
|
||||
// If the connection is being aborted cancel the transport. This will
|
||||
// insure that the transport will go away even if it is blocked waiting
|
||||
// for the consumer to empty the pipe...
|
||||
//
|
||||
if (NS_FAILED(rv)) {
|
||||
mFileTransport->Cancel();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _ns_DiskCacheRecordChannel_h_
|
||||
#define _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
/*
|
||||
* This class is plagiarized from nsMemCacheChannel
|
||||
*/
|
||||
|
||||
class nsDiskCacheRecordChannel : public nsIChannel,
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
|
||||
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsDiskCacheRecordChannel() ;
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
// Declare nsIStreamObserver methods
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// Declare nsIStreamListener methods
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsresult Init(void) ;
|
||||
|
||||
private:
|
||||
|
||||
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
|
||||
|
||||
nsDiskCacheRecord* mRecord ;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup ;
|
||||
nsCOMPtr<nsISupports> mOwner ;
|
||||
nsCOMPtr<nsIChannel> mFileTransport ;
|
||||
nsFileSpec mSpec ;
|
||||
nsCOMPtr<nsIStreamListener> mRealListener;
|
||||
|
||||
friend class WriteStreamWrapper ;
|
||||
} ;
|
||||
|
||||
#endif // _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NS_IDBACCESSOR_H_
|
||||
#define _NS_IDBACCESSOR_H_
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFileSpec.h"
|
||||
|
||||
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
|
||||
#define NS_IDBACCESSOR_IID \
|
||||
{ 0x6aadd4d0, 0x7785, 0x11d3, \
|
||||
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
|
||||
|
||||
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
|
||||
#define NS_DBACCESSOR_CID \
|
||||
{ 0x6aadd4d1, 0x7785, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
class nsIDBAccessor : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
|
||||
NS_IMETHOD Shutdown(void) = 0 ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) = 0 ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
} ;
|
||||
|
||||
#endif // _NS_IDBACCESSOR_H_
|
||||
|
||||
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
@@ -0,0 +1,704 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prtypes.h"
|
||||
#include "prio.h"
|
||||
#include "prsystem.h" // Directory Seperator
|
||||
#include "plhash.h"
|
||||
#include "prclist.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "mcom_db.h"
|
||||
#include "nsDBEnumerator.h"
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
|
||||
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
|
||||
|
||||
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
|
||||
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
|
||||
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
|
||||
|
||||
class nsDiskCacheRecord ;
|
||||
|
||||
nsNetDiskCache::nsNetDiskCache() :
|
||||
m_Enabled(PR_TRUE) ,
|
||||
m_NumEntries(0) ,
|
||||
m_pNextCache(0) ,
|
||||
m_pDiskCacheFolder(0) ,
|
||||
m_StorageInUse(0) ,
|
||||
m_DB(0) ,
|
||||
m_DBCorrupted(PR_FALSE)
|
||||
{
|
||||
// set it to INF for now
|
||||
m_MaxEntries = (PRUint32)-1 ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsNetDiskCache::~nsNetDiskCache()
|
||||
{
|
||||
SetSpecialEntry() ;
|
||||
|
||||
NS_IF_RELEASE(m_DB) ;
|
||||
|
||||
|
||||
// FUR
|
||||
// I think that, eventually, we also want a distinguished key in the DB which
|
||||
// means "clean cache shutdown". You clear this flag when the db is first
|
||||
// opened and set it just before the db is closed. If the db wasn't shutdown
|
||||
// cleanly in a prior session, i.e. because the app crashed, on startup you
|
||||
// scan all the individual files in directories and look for "orphans",
|
||||
// i.e. cache files which don't have corresponding entries in the db. That's
|
||||
// also when storage-in-use and number of entries would be recomputed.
|
||||
//
|
||||
// We don't necessarily need all this functionality immediately, though.
|
||||
|
||||
|
||||
if(m_DBCorrupted) {
|
||||
|
||||
nsFileSpec cacheFolder ;
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheFolder) ;
|
||||
|
||||
char nameInt[6] ;
|
||||
|
||||
for(nsDirectoryIterator di(cacheFolder, PR_FALSE); di.Exists(); di++) {
|
||||
char* filename = di.Spec().GetLeafName() ;
|
||||
char* pname = nameInt ;
|
||||
pname = PL_strncpyz(pname, filename, 6) ;
|
||||
|
||||
if(PL_strcmp(pname, "trash") == 0)
|
||||
RemoveFolder(di.Spec()) ;
|
||||
|
||||
nsCRT::free(filename) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Init(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
// don't initialize if no cache folder is set.
|
||||
if(!m_pDiskCacheFolder) return NS_OK ;
|
||||
|
||||
if(!m_DB) {
|
||||
m_DB = new nsDBAccessor() ;
|
||||
if(!m_DB)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
else
|
||||
NS_ADDREF(m_DB) ;
|
||||
}
|
||||
|
||||
// create cache sub directories
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir->AppendRelativeUnixPath (dirName) ;
|
||||
CreateDir(cacheSubDir);
|
||||
}
|
||||
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::InitDB(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(!m_DBFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
|
||||
if(!m_DBFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
m_DBFile->AppendRelativeUnixPath("cache.db") ;
|
||||
|
||||
rv = m_DB->Init(m_DBFile) ;
|
||||
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
rv = GetSpecialEntry() ;
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports methods
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsNetDiskCache,
|
||||
nsINetDataDiskCache,
|
||||
nsINetDataCache,
|
||||
nsISupports)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCache Method
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
|
||||
{
|
||||
nsAutoString description("Disk Cache") ;
|
||||
*aDescription = description.ToNewUnicode() ;
|
||||
if(!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/* don't alloc mem for nsICachedNetData.
|
||||
* RecordID is generated using the same scheme in nsCacheDiskData,
|
||||
* see GetCachedNetData() for detail.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
nsresult rv = m_DB->GetID(key, length, &id) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
/* regardless if it's cached or not, a copy of nsNetDiskCache would
|
||||
* always be returned. so release it appropriately.
|
||||
* if mem alloced, updata m_NumEntries also.
|
||||
* for now, the new nsCachedNetData is not written into db yet since
|
||||
* we have nothing to write.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
nsresult rv = 0 ;
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
rv = m_DB->GetID(key, length, &id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// construct an empty record
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
rv = newRecord->Init(key, length, id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
delete newRecord ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// this is a previously cached record
|
||||
nsresult r1 ;
|
||||
r1 = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return NS_OK ;
|
||||
else {
|
||||
// probably a bad one
|
||||
NS_RELEASE(newRecord) ;
|
||||
*_retval = nsnull ;
|
||||
return r1;
|
||||
}
|
||||
|
||||
} else if (NS_SUCCEEDED(rv) && !info) {
|
||||
// this is a new record.
|
||||
m_NumEntries ++ ;
|
||||
return NS_OK ;
|
||||
} else {
|
||||
// database error.
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(RecordID, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// construct an empty record if only found in db
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
rv = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
// bad record, I guess
|
||||
NS_RELEASE(newRecord) ; // release if bad things happen
|
||||
return rv ;
|
||||
}
|
||||
} else {
|
||||
NS_ERROR("Error: RecordID not in DB\n") ;
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
*aEnabled = m_Enabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
m_Enabled = aEnabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
*aFlags = FILE_PER_URL_CACHE;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
*aNumEntries = m_NumEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
*aMaxEntries = m_MaxEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
|
||||
if(enumerator) {
|
||||
NS_ADDREF(enumerator) ;
|
||||
*_retval = enumerator ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
|
||||
{
|
||||
if(!aNextCache)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aNextCache = m_pNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
|
||||
{
|
||||
m_pNextCache = aNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// db size can always be measured at the last minute. Since it's hard
|
||||
// to know before hand.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRUint32 total_size = m_StorageInUse ;
|
||||
|
||||
/*
|
||||
PRUint32 len = 0 ;
|
||||
// add the size of the db.
|
||||
m_DB->GetDBFilesize(&len) ;
|
||||
total_size += len ;
|
||||
*/
|
||||
|
||||
// we need size in kB
|
||||
total_size = total_size >> 10 ;
|
||||
|
||||
*aStorageInUse = total_size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* The whole cache dirs can be whiped clean since all the cache
|
||||
* files are resides in seperate hashed dirs. It's safe to do so.
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveAll(void)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
// remove all the sub folders
|
||||
nsFileSpec cacheSubDir;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheSubDir) ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir += dirName ;
|
||||
RemoveFolder(cacheSubDir) ;
|
||||
}
|
||||
|
||||
// don't forget the db file itself
|
||||
m_DB->Shutdown() ;
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// reinitilize
|
||||
return Init() ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsINetDataDiskCache methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
|
||||
{
|
||||
*aDiskCacheFolder = nsnull ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
*aDiskCacheFolder = m_pDiskCacheFolder ;
|
||||
NS_ADDREF(*aDiskCacheFolder) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
|
||||
{
|
||||
if(!m_pDiskCacheFolder) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
|
||||
if(!m_pDiskCacheFolder)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
return Init() ;
|
||||
}
|
||||
else {
|
||||
char *newfolder, *oldfolder ;
|
||||
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
|
||||
aDiskCacheFolder->GetNativePath(&newfolder) ;
|
||||
|
||||
if(PL_strcmp(newfolder, oldfolder) != 0) {
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
|
||||
// do we need to blow away old cache before building a new one?
|
||||
// return RemoveAll() ;
|
||||
|
||||
m_DB->Shutdown() ;
|
||||
return Init() ;
|
||||
|
||||
} else
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsNetDiskCache methods
|
||||
|
||||
// create a directory (recursively)
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
|
||||
{
|
||||
PRBool does_exist ;
|
||||
nsCOMPtr<nsIFileSpec> p_spec ;
|
||||
|
||||
dir_spec->Exists(&does_exist) ;
|
||||
if(does_exist)
|
||||
return NS_OK ;
|
||||
|
||||
nsresult rv = dir_spec->GetParent(getter_AddRefs(p_spec)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
p_spec->Exists(&does_exist) ;
|
||||
if(!does_exist) {
|
||||
CreateDir(p_spec) ;
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
else {
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// We can't afford to make a *separate* pass over the whole db on every
|
||||
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
|
||||
// several second operation on a large db). We'll likely need to store
|
||||
// distinguished keys in the db that contain these values and update them
|
||||
// incrementally, except when failure to shut down the db cleanly is detected.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetSpecialEntry(void)
|
||||
{
|
||||
void* pInfo ;
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
nsresult rv = m_DB->GetSpecialEntry(&pInfo, &InfoSize) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(!pInfo && InfoSize == 0) {
|
||||
// must be a new DB
|
||||
m_NumEntries = 0 ;
|
||||
m_StorageInUse = 0 ;
|
||||
}
|
||||
else {
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
// get m_NumEntries
|
||||
COPY_INT32(&m_NumEntries, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get m_StorageInUse
|
||||
COPY_INT32(&m_StorageInUse, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetSpecialEntry(void)
|
||||
{
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
InfoSize = sizeof m_NumEntries ;
|
||||
InfoSize += sizeof m_StorageInUse ;
|
||||
|
||||
void* pInfo = nsAllocator::Alloc(InfoSize*sizeof(char)) ;
|
||||
if(!pInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_NumEntries) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_StorageInUse) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
|
||||
return m_DB->SetSpecialEntry(pInfo, InfoSize) ;
|
||||
}
|
||||
|
||||
// this routine will be called everytime we have a db corruption.
|
||||
// m_DB will be re-initialized, m_StorageInUse and m_NumEntries will
|
||||
// be reset.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::DBRecovery(void)
|
||||
{
|
||||
// rename all the sub cache dirs and remove them later during dtor.
|
||||
nsresult rv = RenameCacheSubDirs() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// remove corrupted db file, don't care if db->shutdown fails or not.
|
||||
m_DB->Shutdown() ;
|
||||
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// make sure it's not there any more
|
||||
PRBool exists = dbfile.Exists() ;
|
||||
if(exists) {
|
||||
NS_ERROR("can't remove old db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// reinitilize DB
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
// this routine will add string "trash" to current CacheSubDir names.
|
||||
// e.g. 00->trash00, 1f->trash1f. and update the m_DBCorrupted.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RenameCacheSubDirs(void)
|
||||
{
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char oldName[3], newName[8];
|
||||
PR_snprintf(oldName, 3, "%0.2x", i) ;
|
||||
cacheSubDir->AppendRelativeUnixPath(oldName) ;
|
||||
|
||||
// re-name the directory
|
||||
PR_snprintf(newName, 8, "trash%0.2x", i) ;
|
||||
rv = cacheSubDir->Rename(newName) ;
|
||||
if(NS_FAILED(rv))
|
||||
// TODO, error checking
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// update m_DBCorrupted
|
||||
m_DBCorrupted = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine is used by dtor and RemoveAll() to clean up dirs.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveFolder(nsFileSpec aFolder)
|
||||
{
|
||||
for(nsDirectoryIterator di(aFolder, PR_FALSE); di.Exists(); di++) {
|
||||
di.Spec().Delete(PR_TRUE) ;
|
||||
}
|
||||
|
||||
aFolder.Delete(PR_FALSE) ; // recursive delete
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsNetDiskCache is the main disk cache module that will create
|
||||
* the cache database, and then store and retrieve nsDiskCacheRecord
|
||||
* objects from it. It also contains some basic error recovery procedure.
|
||||
*/
|
||||
|
||||
#ifndef __gen_nsNetDiskCache_h__
|
||||
#define __gen_nsNetDiskCache_h__
|
||||
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
class nsIURI; /* forward decl */
|
||||
class nsICachedNetData; /* forward decl */
|
||||
class nsISimpleEnumerator; /* forward decl */
|
||||
class nsIFileSpec; /* forward decl */
|
||||
|
||||
/* starting interface: nsNetDiskCache */
|
||||
|
||||
class nsNetDiskCache : public nsINetDataDiskCache {
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHE
|
||||
NS_DECL_NSINETDATADISKCACHE
|
||||
|
||||
NS_IMETHOD Init(void) ;
|
||||
|
||||
nsNetDiskCache() ;
|
||||
virtual ~nsNetDiskCache() ;
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD InitDB(void) ;
|
||||
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
|
||||
NS_IMETHOD GetSpecialEntry(void) ;
|
||||
NS_IMETHOD SetSpecialEntry(void) ;
|
||||
|
||||
NS_IMETHOD RenameCacheSubDirs(void) ;
|
||||
NS_IMETHOD DBRecovery(void) ;
|
||||
NS_IMETHOD RemoveFolder(nsFileSpec aFolder) ;
|
||||
|
||||
private:
|
||||
|
||||
PRBool m_Enabled ;
|
||||
PRUint32 m_NumEntries ;
|
||||
nsCOMPtr<nsINetDataCache> m_pNextCache ;
|
||||
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
|
||||
nsCOMPtr<nsIFileSpec> m_DBFile ;
|
||||
|
||||
PRUint32 m_MaxEntries ;
|
||||
PRUint32 m_StorageInUse ;
|
||||
nsIDBAccessor* m_DB ;
|
||||
|
||||
// this is used to indicate a db corruption
|
||||
PRBool m_DBCorrupted ;
|
||||
|
||||
friend class nsDiskCacheRecord ;
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
} ;
|
||||
|
||||
#endif /* __gen_nsNetDiskCache_h__ */
|
||||
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _nsNetDiskCacheCID_h_
|
||||
#define _nsNetDiskCacheCID_h_
|
||||
|
||||
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
|
||||
|
||||
#define NS_NETDISKCACHE_CID \
|
||||
{ 0xecfeea00, 0x7201, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
#endif /* _nsNetDiskCacheCID_h_ */
|
||||
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
REQUIRES = libreg xpcom
|
||||
|
||||
CPPSRCS = \
|
||||
diskcache.cpp \
|
||||
$(NULL)
|
||||
|
||||
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
|
||||
|
||||
ifdef NO_LD_ARCHIVE_FLAGS
|
||||
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
|
||||
endif
|
||||
|
||||
LIBS = \
|
||||
-lmozjs \
|
||||
-lxpcom \
|
||||
-lmozdbm_s \
|
||||
$(MOZ_NECKO_UTIL_LIBS) \
|
||||
$(LOST_SYM_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/..
|
||||
|
||||
DEFINES += -DUSE_NSREG -DCACHE
|
||||
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
@@ -0,0 +1,836 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
//#include "nsMemCacheCID.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mChannel = aChannel;
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
// Release channel
|
||||
mChannel = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(channel, testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
nsCOMPtr<nsIFileSpec> file ;
|
||||
record->GetFilename(getter_AddRefs(file)) ;
|
||||
char* name ;
|
||||
file->GetUnixStyleFilePath(&name) ;
|
||||
printf(" file name is %s \n", name) ;
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
PRUint32 len = 0 ;
|
||||
CounterStream *counterStream;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 257; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
truncate(name, startingOffset) ;
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset ;
|
||||
ras->Tell(&offset) ;
|
||||
// printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = 208;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset = 0 ;
|
||||
ras->Tell(&offset) ;
|
||||
printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
*/
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() & 0xffff;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
initPref() ;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXPORTS=nsMemCacheCID.h \
|
||||
nsMemCache.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsMemCache.cpp \
|
||||
nsMemCacheRecord.cpp \
|
||||
nsMemCacheChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
42
mozilla/netwerk/cache/memcache/makefile.win
vendored
Normal file
42
mozilla/netwerk/cache/memcache/makefile.win
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsMemCache.obj \
|
||||
.\$(OBJDIR)\nsMemCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsMemCacheChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsMemCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
@@ -0,0 +1,334 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsHashtableEnumerator.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
||||
PRInt32 nsMemCache::gRecordSerialNumber = 0;
|
||||
|
||||
nsMemCache::nsMemCache()
|
||||
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
|
||||
mHashTable(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCache::~nsMemCache()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
|
||||
"Failure to shut down memory cache. "
|
||||
"Somewhere, someone is holding references to at least one cache record");
|
||||
delete mHashTable;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCache::Init()
|
||||
{
|
||||
mHashTable = new nsHashtable(256);
|
||||
if (!mHashTable)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetDescription(PRUnichar * *aDescription)
|
||||
{
|
||||
nsAutoString description("Memory Cache");
|
||||
*aDescription = description.ToNewUnicode();
|
||||
if (!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
|
||||
{
|
||||
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
*aFound = mHashTable->Exists(opaqueKey);
|
||||
delete opaqueKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsresult rv;
|
||||
nsMemCacheRecord* record = 0;
|
||||
nsOpaqueKey *opaqueKey2 = 0;
|
||||
nsOpaqueKey *opaqueKey3 = 0;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
goto out_of_memory;
|
||||
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
|
||||
delete opaqueKey;
|
||||
|
||||
// No existing cache database entry was found. Create a new one.
|
||||
// This requires two mappings in the hash table:
|
||||
// Record ID ==> record
|
||||
// Opaque key ==> record
|
||||
if (!record) {
|
||||
record = new nsMemCacheRecord;
|
||||
if (!record)
|
||||
goto out_of_memory;
|
||||
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
|
||||
if (NS_FAILED(rv)) goto out_of_memory;
|
||||
|
||||
// Index the record by opaque key
|
||||
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
|
||||
if (!opaqueKey2) goto out_of_memory;
|
||||
mHashTable->Put(opaqueKey2, record);
|
||||
|
||||
// Index the record by it's record ID
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
|
||||
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
|
||||
sizeof record->mRecordID);
|
||||
if (!opaqueKey3) {
|
||||
// Clean up the first record from the hash table
|
||||
mHashTable->Remove(opaqueKey);
|
||||
goto out_of_memory;
|
||||
}
|
||||
mHashTable->Put(opaqueKey3, record);
|
||||
|
||||
// The hash table holds on to the record
|
||||
record->AddRef();
|
||||
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
mNumEntries++;
|
||||
}
|
||||
|
||||
record->AddRef();
|
||||
*aRecord = record;
|
||||
return NS_OK;
|
||||
|
||||
out_of_memory:
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
delete record;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
|
||||
sizeof RecordID);
|
||||
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
|
||||
if (*aRecord) {
|
||||
NS_ADDREF(*aRecord);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMemCache::Delete(nsMemCacheRecord* aRecord)
|
||||
{
|
||||
nsMemCacheRecord *removedRecord;
|
||||
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
|
||||
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
|
||||
sizeof aRecord->mRecordID);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
aRecord->Release();
|
||||
|
||||
mNumEntries--;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG(aEnabled);
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
mEnabled = aEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
NS_ENSURE_ARG(aFlags);
|
||||
*aFlags = MEMORY_CACHE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aNumEntries);
|
||||
*aNumEntries = mNumEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aMaxEntries);
|
||||
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
HashEntryConverter(nsHashKey *aKey, void *aValue,
|
||||
void *unused, nsISupports **retval)
|
||||
{
|
||||
nsMemCacheRecord *record;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
record = (nsMemCacheRecord*)aValue;
|
||||
opaqueKey = (nsOpaqueKey*)aKey;
|
||||
|
||||
// Hash table keys that index cache entries by their record ID
|
||||
// shouldn't be enumerated.
|
||||
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt32 recordID;
|
||||
record->GetRecordID(&recordID);
|
||||
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
|
||||
"Key has incorrect key length");
|
||||
#endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(record);
|
||||
*retval = NS_STATIC_CAST(nsISupports*, record);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> iterator;
|
||||
|
||||
NS_ENSURE_ARG(aIterator);
|
||||
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
|
||||
mHashTable, getter_AddRefs(iterator));
|
||||
return NS_NewAdapterEnumerator(aIterator, iterator);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
|
||||
{
|
||||
NS_ENSURE_ARG(aNextCache);
|
||||
*aNextCache = mNextCache;
|
||||
NS_ADDREF(*aNextCache);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
|
||||
{
|
||||
mNextCache = aNextCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ENSURE_ARG(aStorageInUse);
|
||||
|
||||
// Convert from bytes to KB
|
||||
*aStorageInUse = (mOccupancy >> 10);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::RemoveAll(void)
|
||||
{
|
||||
PRBool failed;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> recordSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsresult rv;
|
||||
|
||||
failed = PR_FALSE;
|
||||
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(recordSupports));
|
||||
record = do_QueryInterface(recordSupports);
|
||||
recordSupports = 0;
|
||||
|
||||
PRUint32 bytesUsed;
|
||||
record->GetStoredContentLength(&bytesUsed);
|
||||
rv = record->Delete();
|
||||
if (NS_FAILED(rv)) {
|
||||
failed = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
mOccupancy -= bytesUsed;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCache_h_
|
||||
#define _nsMemCache_h_
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
|
||||
// Maximum number of URIs that may be resident in the cache
|
||||
#define MEM_CACHE_MAX_ENTRIES 1000
|
||||
|
||||
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
|
||||
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
|
||||
|
||||
class nsHashtable;
|
||||
class nsMemCacheRecord;
|
||||
|
||||
class nsMemCache : public nsINetDataCache
|
||||
{
|
||||
public:
|
||||
nsMemCache();
|
||||
virtual ~nsMemCache();
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCache methods
|
||||
NS_DECL_NSINETDATACACHE
|
||||
|
||||
// Factory
|
||||
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mNumEntries;
|
||||
PRUint32 mOccupancy; // Memory used, in bytes
|
||||
PRBool mEnabled; // If false, bypass mem cache
|
||||
|
||||
nsINetDataCache* mNextCache;
|
||||
|
||||
// Mapping from either opaque key or record ID to nsMemCacheRecord
|
||||
nsHashtable* mHashTable;
|
||||
|
||||
// Used to assign record ID's
|
||||
static PRInt32 gRecordSerialNumber;
|
||||
|
||||
NS_METHOD Delete(nsMemCacheRecord* aRecord);
|
||||
|
||||
friend class nsMemCacheRecord;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCache_h_
|
||||
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// XPCOM Class ID for the network data in-memory cache
|
||||
|
||||
#ifndef nsMEMCACHECID_h__
|
||||
#define nsMEMCACHECID_h__
|
||||
|
||||
// {e4710560-7de2-11d3-90cb-0040056a906e}
|
||||
#define NS_MEM_CACHE_FACTORY_CID \
|
||||
{ \
|
||||
0xe4710560, \
|
||||
0x7de2, \
|
||||
0x11d3, \
|
||||
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#endif // nsMEMCACHECID_h__
|
||||
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
|
||||
|
||||
void
|
||||
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
mRecord->mCache->mOccupancy += aBytesUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class acts as an adaptor around a synchronous input stream to add async
|
||||
* read capabilities. It adds methods for initiating, suspending, resuming and
|
||||
* cancelling async reads.
|
||||
*/
|
||||
class AsyncReadStreamAdaptor : public nsIInputStream {
|
||||
public:
|
||||
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
|
||||
mSyncStream(aSyncStream), mDataAvailCursor(0),
|
||||
mRemaining(0), mAvailable(0), mChannel(aChannel), mAborted(PR_FALSE), mSuspended(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~AsyncReadStreamAdaptor() {
|
||||
mChannel->mAsyncReadStream = 0;
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsresult
|
||||
IsPending(PRBool* aIsPending) {
|
||||
*aIsPending = (mRemaining != 0) && !mAborted;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Suspend(void) { mSuspended = PR_TRUE; return NS_OK; }
|
||||
|
||||
nsresult
|
||||
Resume(void) {
|
||||
if (!mSuspended)
|
||||
return NS_ERROR_FAILURE;
|
||||
mSuspended = PR_FALSE;
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Available(PRUint32 *aNumBytes) { return mAvailable; }
|
||||
|
||||
NS_IMETHOD
|
||||
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
|
||||
if (mAborted)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
*aBytesRead = 0;
|
||||
aCount = PR_MIN(aCount, mAvailable);
|
||||
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
|
||||
mAvailable -= *aBytesRead;
|
||||
|
||||
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mSuspended && !mAvailable) {
|
||||
rv = NextListenerEvent();
|
||||
if (NS_FAILED(rv)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Close() {
|
||||
nsresult rv = mSyncStream->Close();
|
||||
mSyncStream = 0;
|
||||
mContext = 0;
|
||||
mStreamListener = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports* aContext, nsIStreamListener* aListener) {
|
||||
|
||||
nsresult rv;
|
||||
nsIEventQueue *eventQ;
|
||||
|
||||
mContext = aContext;
|
||||
mStreamListener = aListener;
|
||||
mRemaining = aReadCount;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewAsyncStreamListener(aListener, eventQ,
|
||||
getter_AddRefs(mStreamListener));
|
||||
NS_RELEASE(eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mStreamListener->OnStartRequest(mChannel, aContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
nsresult
|
||||
Fail(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NextListenerEvent() {
|
||||
PRUint32 available;
|
||||
nsresult rv = mSyncStream->Available(&available);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
available -= mAvailable;
|
||||
available = PR_MIN(available, mRemaining);
|
||||
|
||||
if (available) {
|
||||
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
|
||||
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
|
||||
mDataAvailCursor, size);
|
||||
mDataAvailCursor += size;
|
||||
mRemaining -= size;
|
||||
mAvailable += size;
|
||||
return rv;
|
||||
} else {
|
||||
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
|
||||
AsyncReadStreamAdaptor* thisAlias = this;
|
||||
NS_RELEASE(thisAlias);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
|
||||
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
|
||||
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
|
||||
// being converted to an async stream
|
||||
PRUint32 mDataAvailCursor;
|
||||
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
|
||||
// consumer OnDataAvailable's that were fired
|
||||
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
|
||||
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
|
||||
// but can not use nsCOMPtr
|
||||
PRBool mAborted; // Abort() has been called
|
||||
PRBool mSuspended; // Suspend() has been called
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
|
||||
|
||||
// The only purpose of this output stream wrapper is to adjust the cache's
|
||||
// overall occupancy as new data flows into the cache entry.
|
||||
class MemCacheWriteStreamWrapper : public nsIOutputStream {
|
||||
public:
|
||||
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
|
||||
mBaseStream(aBaseStream), mChannel(aChannel)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
|
||||
|
||||
static nsresult
|
||||
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
|
||||
MemCacheWriteStreamWrapper *wrapper =
|
||||
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Flush() { return mBaseStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Close() { return mBaseStream->Close(); }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
nsMemCacheChannel* mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mRecord->mNumChannels++;
|
||||
}
|
||||
|
||||
nsMemCacheChannel::~nsMemCacheChannel()
|
||||
{
|
||||
mRecord->mNumChannels--;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::IsPending(PRBool* aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE;
|
||||
if (!mAsyncReadStream)
|
||||
return NS_OK;
|
||||
return mAsyncReadStream->IsPending(aIsPending);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Cancel(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Cancel();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Suspend(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Suspend();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Resume(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Resume();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
if (mInputStream)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
|
||||
*aResult = mInputStream;
|
||||
NS_ADDREF(*aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
|
||||
PRUint32 oldLength;
|
||||
mRecord->mStorageStream->GetLength(&oldLength);
|
||||
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (startPosition < oldLength)
|
||||
NotifyStorageInUse(startPosition - oldLength);
|
||||
|
||||
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
|
||||
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
|
||||
if (!asyncReadStreamAdaptor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(asyncReadStreamAdaptor);
|
||||
mAsyncReadStream = asyncReadStreamAdaptor;
|
||||
|
||||
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
|
||||
if (NS_FAILED(rv))
|
||||
delete asyncReadStreamAdaptor;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
|
||||
PRInt32 writeCount, nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
{
|
||||
// Not required to be implemented
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentType(char* *aContentType)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get();
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
mOwner = aOwner;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheChannel_h_
|
||||
#define _nsMemCacheChannel_h_
|
||||
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
class AsyncReadStreamAdaptor;
|
||||
|
||||
class nsMemCacheChannel : public nsIChannel
|
||||
{
|
||||
public:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsMemCacheChannel();
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
protected:
|
||||
void NotifyStorageInUse(PRInt32 aBytesUsed);
|
||||
|
||||
nsCOMPtr<nsMemCacheRecord> mRecord;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
|
||||
|
||||
friend class MemCacheWriteStreamWrapper;
|
||||
friend class AsyncReadStreamAdaptor;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheChannel_h_
|
||||
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsStorageStream.h"
|
||||
|
||||
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
|
||||
|
||||
nsMemCacheRecord::nsMemCacheRecord()
|
||||
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCacheRecord::~nsMemCacheRecord()
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
if (mKey)
|
||||
delete[] mKey;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mKey, mKeyLength);
|
||||
*aLength = mKeyLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
|
||||
|
||||
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
|
||||
getter_AddRefs(mStorageStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mKey = new char[aKeyLength];
|
||||
if (!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mKey, aKey, aKeyLength);
|
||||
mKeyLength = aKeyLength;
|
||||
mRecordID = aRecordID;
|
||||
mCache = aCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
|
||||
{
|
||||
NS_ENSURE_ARG(aRecordID);
|
||||
*aRecordID = mRecordID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
*aResult = 0;
|
||||
if (mMetaDataLength) {
|
||||
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mMetaData, mMetaDataLength);
|
||||
}
|
||||
*aLength = mMetaDataLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
mMetaData = new char[aLength];
|
||||
if (!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mMetaData, aData, aLength);
|
||||
mMetaDataLength = aLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
NS_ENSURE_ARG(aStoredContentLength);
|
||||
return mStorageStream->GetLength(aStoredContentLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 before, after;
|
||||
mStorageStream->GetLength(&before);
|
||||
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mStorageStream->GetLength(&after);
|
||||
mCache->mOccupancy -= (before - after);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::Delete(void)
|
||||
{
|
||||
if (mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return mCache->Delete(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
|
||||
if (!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(channel);
|
||||
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheRecord_h_
|
||||
#define _nsMemCacheRecord_h_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsMemCache;
|
||||
|
||||
class nsMemCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
|
||||
public:
|
||||
// Declare interface methods
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheRecord();
|
||||
virtual ~nsMemCacheRecord();
|
||||
|
||||
nsresult Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache);
|
||||
|
||||
char* mKey; // opaque database key for this record
|
||||
PRUint32 mKeyLength; // length, in bytes, of mKey
|
||||
|
||||
PRInt32 mRecordID; // An alternate key for this record
|
||||
|
||||
char* mMetaData; // opaque URI metadata
|
||||
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
|
||||
|
||||
nsMemCache* mCache; // weak pointer to the cache database
|
||||
// that this record inhabits
|
||||
|
||||
nsCOMPtr<nsIStorageStream> mStorageStream;
|
||||
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
|
||||
|
||||
friend class nsMemCache;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheRecord_h_
|
||||
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
REQUIRES = nspr
|
||||
|
||||
EXPORTS = \
|
||||
nsCacheManager.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsCacheManager.cpp \
|
||||
nsCachedNetData.cpp \
|
||||
nsReplacementPolicy.cpp \
|
||||
nsCacheEntryChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsCacheManager.obj \
|
||||
.\$(OBJDIR)\nsCachedNetData.obj \
|
||||
.\$(OBJDIR)\nsReplacementPolicy.obj \
|
||||
.\$(OBJDIR)\nsCacheEntryChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCacheEntryChannel.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup):
|
||||
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
|
||||
{
|
||||
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
|
||||
mCacheEntry->mChannelCount++;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheEntryChannel::~nsCacheEntryChannel()
|
||||
{
|
||||
mCacheEntry->mChannelCount--;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
|
||||
|
||||
// A proxy for nsIOutputStream
|
||||
class CacheOutputStream : public nsIOutputStream {
|
||||
|
||||
public:
|
||||
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
|
||||
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheOutputStream() {
|
||||
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
|
||||
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Close() {
|
||||
return mOutputStream->Close();
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
|
||||
nsresult rv;
|
||||
|
||||
*aActualBytes = 0;
|
||||
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
|
||||
mCacheEntry->mLogicalLength += *aActualBytes;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCacheManager::LimitCacheSize();
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
|
||||
// Time at which stream was opened
|
||||
PRTime mStartTime;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIOutputStream> baseOutputStream;
|
||||
|
||||
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mCacheEntry->NoteUpdate();
|
||||
mCacheEntry->NoteAccess();
|
||||
mCacheEntry->mLogicalLength = aStartPosition;
|
||||
|
||||
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
|
||||
if (!*aOutputStream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aOutputStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream)
|
||||
{
|
||||
mCacheEntry->NoteAccess();
|
||||
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
|
||||
}
|
||||
|
||||
class CacheManagerStreamListener: public nsIStreamListener {
|
||||
|
||||
public:
|
||||
|
||||
CacheManagerStreamListener(nsIStreamListener *aListener,
|
||||
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
|
||||
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheManagerStreamListener() {}
|
||||
|
||||
private:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
|
||||
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
|
||||
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->AddChannel(mChannel, aContext);
|
||||
return mListener->OnStartRequest(mChannel, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
|
||||
nsresult status, const PRUnichar *errorMsg) {
|
||||
nsresult rv;
|
||||
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mCacheEntry->NoteAccess();
|
||||
|
||||
nsCOMPtr<nsIStreamListener> headListener;
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
|
||||
|
||||
// Create a load group "proxy" listener...
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (NS_SUCCEEDED(rv) && factory) {
|
||||
rv = factory->CreateLoadGroupListener(aListener,
|
||||
getter_AddRefs(headListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
headListener = aListener;
|
||||
}
|
||||
|
||||
CacheManagerStreamListener* cacheManagerStreamListener;
|
||||
nsIChannel *channelForListener;
|
||||
|
||||
channelForListener = mProxyChannel ? mProxyChannel.get() : NS_STATIC_CAST(nsIChannel*, this);
|
||||
cacheManagerStreamListener =
|
||||
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
|
||||
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(cacheManagerStreamListener);
|
||||
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
|
||||
cacheManagerStreamListener);
|
||||
NS_RELEASE(cacheManagerStreamListener);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// No async writes allowed to the cache yet
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
*aLoadGroup = mLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
*aLoadAttributes = mLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
mLoadAttributes = aLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
char* spec;
|
||||
nsresult rv;
|
||||
|
||||
rv = mCacheEntry->GetUriSpec(&spec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = serv->NewURI(spec, 0, aURI);
|
||||
nsAllocator::Free(spec);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// FIXME - should return original URI passed into NewChannel() ?
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheEntryChannel_h_
|
||||
#define _nsCacheEntryChannel_h_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
|
||||
// A proxy for an nsIChannel, useful when only a few nsIChannel
|
||||
// methods must be overridden
|
||||
class nsChannelProxy : public nsIChannel {
|
||||
|
||||
public:
|
||||
NS_FORWARD_NSICHANNEL(mChannel->)
|
||||
NS_FORWARD_NSIREQUEST(mChannel->)
|
||||
|
||||
protected:
|
||||
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
|
||||
virtual ~nsChannelProxy() {};
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
// Override several nsIChannel methods so that they interact with the cache manager
|
||||
class nsCacheEntryChannel : public nsChannelProxy {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
|
||||
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream);
|
||||
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener);
|
||||
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver);
|
||||
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
|
||||
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
|
||||
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
|
||||
NS_IMETHOD GetURI(nsIURI * *aURI);
|
||||
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
|
||||
|
||||
protected:
|
||||
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
|
||||
virtual ~nsCacheEntryChannel();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mProxyChannel;
|
||||
nsLoadFlags mLoadAttributes;
|
||||
};
|
||||
|
||||
#endif // _nsCacheEntryChannel_h_
|
||||
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
|
||||
// Limit the number of entries in the cache to conserve memory space
|
||||
// in the nsReplacementPolicy code
|
||||
#define MAX_MEM_CACHE_ENTRIES 800
|
||||
#define MAX_DISK_CACHE_ENTRIES 3200
|
||||
|
||||
// Cache capacities in MB, overridable via APIs
|
||||
#define DEFAULT_MEMORY_CACHE_CAPACITY 1024
|
||||
#define DEFAULT_DISK_CACHE_CAPACITY 10000
|
||||
|
||||
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
|
||||
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
|
||||
|
||||
nsCacheManager* gCacheManager = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
|
||||
|
||||
nsCacheManager::nsCacheManager()
|
||||
: mActiveCacheRecords(0),
|
||||
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
|
||||
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
|
||||
{
|
||||
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
|
||||
gCacheManager = this;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheManager::~nsCacheManager()
|
||||
{
|
||||
gCacheManager = 0;
|
||||
delete mActiveCacheRecords;
|
||||
delete mMemSpaceManager;
|
||||
delete mDiskSpaceManager;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mActiveCacheRecords = new nsHashtable(64);
|
||||
if (!mActiveCacheRecords)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Instantiate the memory cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mMemCache));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
|
||||
getter_AddRefs(mFlatCache));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// For now, we don't require a flat cache module to be present
|
||||
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef FILE_CACHE_IS_READY
|
||||
// Instantiate the file cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mFileCache));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("No disk cache present");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up linked list of caches in search order
|
||||
mCacheSearchChain = mMemCache;
|
||||
if (mFlatCache) {
|
||||
mMemCache->SetNextCache(mFlatCache);
|
||||
mFlatCache->SetNextCache(mFileCache);
|
||||
} else {
|
||||
mMemCache->SetNextCache(mFileCache);
|
||||
}
|
||||
|
||||
// TODO - Load any extension caches here
|
||||
|
||||
// Initialize replacement policy for memory cache module
|
||||
mMemSpaceManager = new nsReplacementPolicy;
|
||||
if (!mMemSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mMemSpaceManager->AddCache(mMemCache);
|
||||
|
||||
// Initialize replacement policy for disk cache modules (file
|
||||
// cache and flat cache)
|
||||
mDiskSpaceManager = new nsReplacementPolicy;
|
||||
if (!mDiskSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (mFileCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFileCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
if (mFlatCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFlatCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, nsICachedNetData* *aResult)
|
||||
{
|
||||
nsCachedNetData *cachedData;
|
||||
nsresult rv;
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
|
||||
// Ensure that cache is initialized
|
||||
if (mDiskCacheCapacity == (PRUint32)-1)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL at end of URI spec
|
||||
cacheKey += '\0';
|
||||
if (aSecondaryKey)
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
// There is no existing instance of nsCachedNetData for this URL.
|
||||
// Make one from the corresponding record in the cache module.
|
||||
if (cachedData) {
|
||||
NS_ASSERTION(cache == cachedData->mCache,
|
||||
"Cannot yet handle simultaneously active requests for the "
|
||||
"same URL using different caches");
|
||||
NS_ADDREF(cachedData);
|
||||
} else {
|
||||
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
|
||||
cache, &cachedData);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mActiveCacheRecords->Put(&key, cachedData);
|
||||
}
|
||||
|
||||
*aResult = cachedData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove this cache entry from the list of active ones
|
||||
nsresult
|
||||
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 keyLength;
|
||||
char* key;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCachedNetData* deletedEntry;
|
||||
|
||||
rv = aEntry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = record->GetKey(&keyLength, &key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey hashTableKey(nsCString(key, keyLength));
|
||||
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
|
||||
// NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, PRBool *aResult)
|
||||
{
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
nsCachedNetData *cachedData;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL between URI spec and secondary key
|
||||
cacheKey += '\0';
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
// Locate the record using (URI + secondary key)
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
if (cachedData && (cache == cachedData->mCache)) {
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
} else {
|
||||
// No active cache entry, see if there is a dormant one
|
||||
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> cacheSupports;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
PRUint32 totalEntries = 0;
|
||||
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(cacheSupports));
|
||||
cache = do_QueryInterface(cacheSupports);
|
||||
|
||||
PRUint32 numEntries;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
totalEntries += numEntries;
|
||||
}
|
||||
|
||||
*aNumEntries = totalEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
class CacheEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheEnumerator() {};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP
|
||||
HasMoreElements(PRBool* aMoreElements) {
|
||||
*aMoreElements = (mCache != 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetNext(nsISupports* *aSupports) {
|
||||
*aSupports = mCache;
|
||||
if (!mCache)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ADDREF(*aSupports);
|
||||
|
||||
nsCOMPtr<nsINetDataCache> nextCache;
|
||||
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
|
||||
mCache = nextCache;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsINetDataCache> mCache;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
*aResult = new CacheEnumerator(mCacheSearchChain);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::RemoveAll(void)
|
||||
{
|
||||
nsresult rv, result;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
|
||||
result = NS_OK;
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(iSupports));
|
||||
cache = do_QueryInterface(iSupports);
|
||||
|
||||
PRUint32 cacheFlags;
|
||||
rv = cache->GetFlags(&cacheFlags);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
|
||||
rv = cache->RemoveAll();
|
||||
if (NS_FAILED(rv))
|
||||
result = rv;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitMemCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mMemSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitDiskCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mDiskSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = LimitDiskCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = LimitMemCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mMemCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mMemCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mDiskCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mDiskCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->SetDiskCacheFolder(aFolder);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->GetDiskCacheFolder(aFolder);
|
||||
}
|
||||
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheManager_h_
|
||||
#define _nsCacheManager_h_
|
||||
|
||||
// 2030f0b0-9567-11d3-90d3-0040056a906e
|
||||
#define NS_CACHE_MANAGER_CID \
|
||||
{ \
|
||||
0x2030f0b0, \
|
||||
0x9567, \
|
||||
0x11d3, \
|
||||
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsHashtable;
|
||||
class nsReplacementPolicy;
|
||||
class nsCachedNetData;
|
||||
|
||||
class nsCacheManager : public nsINetDataCacheManager {
|
||||
|
||||
public:
|
||||
nsCacheManager();
|
||||
virtual ~nsCacheManager();
|
||||
|
||||
NS_METHOD Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCacheManager methods
|
||||
NS_DECL_NSINETDATACACHEMANAGER
|
||||
|
||||
private:
|
||||
|
||||
// Mapping from cache key to nsCachedNetData, but only for those cache
|
||||
// entries with external references, i.e. those referred to outside the
|
||||
// cache manager
|
||||
nsHashtable* mActiveCacheRecords;
|
||||
|
||||
// Memory cache
|
||||
nsCOMPtr<nsINetDataCache> mMemCache;
|
||||
|
||||
// Flat-file database cache; All content aggregated into single disk file
|
||||
nsCOMPtr<nsINetDataCache> mFlatCache;
|
||||
|
||||
// stream-as-file cache
|
||||
nsCOMPtr<nsINetDataCache> mFileCache;
|
||||
|
||||
// Unified replacement policy for flat-cache and file-cache
|
||||
nsReplacementPolicy* mDiskSpaceManager;
|
||||
|
||||
// Replacement policy for memory cache
|
||||
nsReplacementPolicy* mMemSpaceManager;
|
||||
|
||||
// List of caches in search order
|
||||
nsINetDataCache* mCacheSearchChain;
|
||||
|
||||
// Combined file/flat cache capacity, in KB
|
||||
PRUint32 mDiskCacheCapacity;
|
||||
|
||||
// Memory cache capacity, in KB
|
||||
PRUint32 mMemCacheCapacity;
|
||||
|
||||
protected:
|
||||
static nsresult NoteDormant(nsCachedNetData* aEntry);
|
||||
static nsresult LimitCacheSize();
|
||||
static nsresult LimitMemCacheSize();
|
||||
static nsresult LimitDiskCacheSize();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
friend class CacheOutputStream;
|
||||
};
|
||||
|
||||
#endif // _nsCacheManager_h_
|
||||
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCachedNetData_h_
|
||||
#define _nsCachedNetData_h_
|
||||
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
|
||||
class nsINetDataCache;
|
||||
class nsIStreamAsFileObserver;
|
||||
class nsIStreamAsFile;
|
||||
class nsIArena;
|
||||
class StreamAsFileObserverClosure;
|
||||
class CacheMetaData;
|
||||
|
||||
// Number of recent access times recorded
|
||||
#define MAX_K 3
|
||||
|
||||
/**
|
||||
* FIXME - add comment. There are a lot of these data structures resident in
|
||||
* memory, so be careful about adding members unnecessarily.
|
||||
*/
|
||||
class nsCachedNetData : public nsICachedNetData {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsICachedNetData methods
|
||||
NS_DECL_NSICACHEDNETDATA
|
||||
|
||||
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
|
||||
|
||||
protected:
|
||||
|
||||
// Bits for mFlags, below
|
||||
typedef enum {
|
||||
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
|
||||
|
||||
// ==== Flags that can be set by the protocol handler ====
|
||||
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
|
||||
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
|
||||
|
||||
// ==== Cache-entry state flags. At most one of these flags can be set ====
|
||||
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
|
||||
// been truncated by cache manager
|
||||
|
||||
// A previously-used cache entry, which has been purged of all cached
|
||||
// content and protocol-private data. This cache entry can be refilled
|
||||
// with new content or it may be retained in this vestigial state
|
||||
// because the usage statistics it contains will be used by the
|
||||
// replacement policy if the same URI is ever cached again.
|
||||
VESTIGIAL = 1 << 5,
|
||||
|
||||
// ==== Memory usage status bits. At most one of these flags can be set ====
|
||||
RECYCLED = 1 << 8, // Previously associated database record has
|
||||
// been deleted; This cache entry is available
|
||||
// for recycling.
|
||||
|
||||
DORMANT = 1 << 9, // No references to this cache entry, except by
|
||||
// the cache manager itself
|
||||
|
||||
// ==== Setter bits ====
|
||||
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
|
||||
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
|
||||
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
|
||||
|
||||
// ==== Useful flag combinations ====
|
||||
// Cache entry not eligible for eviction
|
||||
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
|
||||
|
||||
// State flags that are in-memory only, i.e. not persistent
|
||||
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
|
||||
} Flag;
|
||||
|
||||
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
|
||||
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
|
||||
|
||||
// Set a boolean flag for the cache entry
|
||||
nsresult SetFlag(PRBool aValue, Flag aFlag);
|
||||
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
|
||||
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
|
||||
|
||||
void ComputeProfit(PRUint32 aCurrentTime);
|
||||
static int Compare(const void *a, const void *b, void *unused);
|
||||
|
||||
void NoteAccess();
|
||||
void NoteUpdate();
|
||||
|
||||
// Get underlying raw cache database record.
|
||||
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
|
||||
|
||||
nsresult GetRecordID(PRInt32 *aRecordID);
|
||||
|
||||
nsresult Evict(PRUint32 aTruncatedContentLength);
|
||||
|
||||
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
|
||||
|
||||
void NoteDownloadTime(PRTime start, PRTime end);
|
||||
|
||||
// placement new for arena-allocation
|
||||
void *operator new (size_t aSize, nsIArena *aArena);
|
||||
|
||||
friend class nsReplacementPolicy;
|
||||
friend class nsCacheManager;
|
||||
friend class StreamAsFile;
|
||||
friend class nsCacheEntryChannel;
|
||||
friend class CacheOutputStream;
|
||||
friend class InterceptStreamListener;
|
||||
|
||||
private:
|
||||
|
||||
nsCachedNetData() {};
|
||||
virtual ~nsCachedNetData() {};
|
||||
|
||||
// Initialize internal fields of this nsCachedNetData instance from the
|
||||
// underlying raw cache database record.
|
||||
nsresult Deserialize(PRBool aDeserializeFlags);
|
||||
|
||||
// Notify stream-as-file observers about change in cache entry status
|
||||
nsresult Notify(PRUint32 aMessage, nsresult aError);
|
||||
|
||||
// Add/Remove stream-as-file observers
|
||||
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
|
||||
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
|
||||
|
||||
// Mark cache entry to indicate a write out to the cache database is required
|
||||
void SetDirty() { mFlags |= DIRTY; }
|
||||
|
||||
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
|
||||
|
||||
nsresult CommitFlags();
|
||||
|
||||
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
|
||||
|
||||
private:
|
||||
|
||||
// List of nsIStreamAsFileObserver's that will receive notification events
|
||||
// when the cache manager or a client desires to delete/truncate a cache
|
||||
// entry file.
|
||||
StreamAsFileObserverClosure* mObservers;
|
||||
|
||||
// Protocol-specific meta-data, opaque to the cache manager
|
||||
CacheMetaData *mMetaData;
|
||||
|
||||
// Next in chain for a single bucket in the replacement policy hash table
|
||||
// that maps from record ID to nsCachedNetData
|
||||
nsCachedNetData* mNext;
|
||||
|
||||
// See flag bits, above
|
||||
// NOTE: 16 bit member is combined with members below for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint16 mFlags;
|
||||
|
||||
protected:
|
||||
|
||||
// Number of nsCacheEntryChannels referring to this record
|
||||
PRUint8 mChannelCount;
|
||||
|
||||
// Below members are statistics kept per cache-entry, used to decide how
|
||||
// profitable it will be to evict a record from the cache relative to other
|
||||
// existing records. Note: times are measured in *seconds* since the
|
||||
// 1/1/70 epoch, same as a unix time_t.
|
||||
|
||||
// Number of accesses for this cache record
|
||||
// NOTE: 8 bit member is combined with members above for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint8 mNumAccesses;
|
||||
|
||||
// A reference to the underlying, raw cache database record, either as a
|
||||
// pointer to an in-memory object or as a database record identifier
|
||||
union {
|
||||
nsINetDataCacheRecord* mRecord;
|
||||
|
||||
// Database record ID of associated cache record. See
|
||||
// nsINetDataCache::GetRecordByID().
|
||||
PRInt32 mRecordID;
|
||||
};
|
||||
|
||||
// Weak link to parent cache
|
||||
nsINetDataCache* mCache;
|
||||
|
||||
// Length of stored content, which may be less than storage consumed if
|
||||
// compression is used
|
||||
PRUint32 mLogicalLength;
|
||||
|
||||
// Most recent cache entry access times, used to compute access frequency
|
||||
PRUint32 mAccessTime[MAX_K];
|
||||
|
||||
// We use modification time of the original document for replacement policy
|
||||
// computations, i.e. to compute a document's age, but if we don't know it,
|
||||
// we use the time that the document was last written to the cache.
|
||||
union {
|
||||
// Document modification time, if known.
|
||||
PRUint32 mLastModifiedTime;
|
||||
|
||||
// Time of last cache update for this doc
|
||||
PRUint32 mLastUpdateTime;
|
||||
};
|
||||
|
||||
union {
|
||||
// Time until which document is fresh, i.e. does not have to be validated
|
||||
// with server and, therefore, data in cache is guaranteed usable
|
||||
PRUint32 mExpirationTime;
|
||||
|
||||
// Heuristic time at which cached document is likely to be out-of-date
|
||||
// with respect to canonical copy on server. Used for cache replacement
|
||||
// policy, not for validation.
|
||||
PRUint32 mStaleTime;
|
||||
};
|
||||
|
||||
// Download time per byte, measure roughly in units of KB/s
|
||||
float mDownloadRate;
|
||||
|
||||
// Heuristic estimate of cache entry future benefits, based on above values
|
||||
float mProfit;
|
||||
};
|
||||
|
||||
#endif // _nsCachedNetData_h_
|
||||
|
||||
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
@@ -0,0 +1,666 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsCachedNetData.h"
|
||||
|
||||
#include "nsQuickSort.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "prtime.h"
|
||||
#include "prbit.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include <math.h>
|
||||
|
||||
// Constant used to estimate frequency of access to a document based on size
|
||||
#define CACHE_CONST_B 1.35
|
||||
|
||||
// A cache whose space is managed by this replacement policy
|
||||
class nsReplacementPolicy::CacheInfo {
|
||||
public:
|
||||
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
|
||||
|
||||
nsINetDataCache* mCache;
|
||||
CacheInfo* mNext;
|
||||
};
|
||||
|
||||
nsReplacementPolicy::nsReplacementPolicy()
|
||||
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
|
||||
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
|
||||
|
||||
nsReplacementPolicy::~nsReplacementPolicy()
|
||||
{
|
||||
if (mRankedEntries)
|
||||
nsAllocator::Free(mRankedEntries);
|
||||
if (mMapRecordIdToEntry)
|
||||
nsAllocator::Free(mMapRecordIdToEntry);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mMaxEntries = aMaxCacheEntries;
|
||||
|
||||
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
|
||||
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
|
||||
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
|
||||
if (!mMapRecordIdToEntry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCRT::zero(mMapRecordIdToEntry, numBytes);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
|
||||
{
|
||||
CacheInfo *cacheInfo = new CacheInfo(aCache);
|
||||
if (!cacheInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
cacheInfo->mNext = mCaches;
|
||||
mCaches = cacheInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
|
||||
{
|
||||
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
|
||||
}
|
||||
|
||||
nsCachedNetData*
|
||||
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCachedNetData* cacheEntry;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntry = mMapRecordIdToEntry[bucket];
|
||||
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
|
||||
|
||||
PRInt32 recordID;
|
||||
rv = cacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add a cache entry to the hash table that maps record ID to entries
|
||||
void
|
||||
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
|
||||
{
|
||||
nsCachedNetData** cacheEntryp;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp)
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
*cacheEntryp = aCacheEntry;
|
||||
aCacheEntry->mNext = 0;
|
||||
}
|
||||
|
||||
// Delete a cache entry from the hash table that maps record ID to entries
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 recordID;
|
||||
rv = aCacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 bucket = HashRecordID(recordID);
|
||||
|
||||
nsCachedNetData** cacheEntryp;
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp) {
|
||||
if (*cacheEntryp == aCacheEntry) {
|
||||
*cacheEntryp = aCacheEntry->mNext;
|
||||
return NS_OK;
|
||||
}
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
}
|
||||
|
||||
NS_ASSERTION(0, "hash table inconsistency");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
rv = iterator->GetNext(getter_AddRefs(iSupports));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
record = do_QueryInterface(iSupports);
|
||||
|
||||
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
static PRUint32
|
||||
now32()
|
||||
{
|
||||
double nowFP;
|
||||
PRInt64 now64 = PR_Now();
|
||||
LL_L2D(nowFP, now64);
|
||||
PRUint32 now = (PRUint32)(nowFP * 1e-6);
|
||||
return now;
|
||||
}
|
||||
|
||||
void
|
||||
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
|
||||
{
|
||||
double startFP, endFP, rate, duration;
|
||||
|
||||
LL_L2D(startFP, start);
|
||||
LL_L2D(endFP, end);
|
||||
|
||||
duration = endFP - startFP;
|
||||
|
||||
// If the data arrives so fast that it can not be timed due to the clock
|
||||
// granularity, assume a data arrival duration of 10 ms
|
||||
if (!duration)
|
||||
duration = 10000;
|
||||
|
||||
// Compute download rate in kB/s
|
||||
rate = mLogicalLength / (duration * (1e-6 * 1024.0));
|
||||
|
||||
if (mDownloadRate) {
|
||||
// Exponentially smooth download rate
|
||||
const double alpha = 0.5;
|
||||
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
|
||||
} else {
|
||||
mDownloadRate = (float)rate;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 hour
|
||||
#define MIN_HALFLIFE (60 * 60)
|
||||
|
||||
// 1 week
|
||||
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
|
||||
|
||||
/**
|
||||
* Estimate the profit that would be lost if the given cache entry was evicted
|
||||
* from the cache. Profit is defined as the future expected download delay per
|
||||
* byte of cached content. The profit computation is made based on projected
|
||||
* frequency of access, prior download performance and a heuristic staleness
|
||||
* criteria. The technique used is a variation of that described in the
|
||||
* following paper:
|
||||
*
|
||||
* "A Case for Delay-Conscious Caching of Web Documents"
|
||||
* http://www.bell-labs.com/user/rvingral/www97.html
|
||||
*
|
||||
* Briefly, expected profit is:
|
||||
*
|
||||
* (projected frequency of access) * (download time per byte) * (probability freshness)
|
||||
*/
|
||||
void
|
||||
nsCachedNetData::ComputeProfit(PRUint32 aNow)
|
||||
{
|
||||
PRUint32 K, now;
|
||||
|
||||
if (aNow)
|
||||
now = aNow;
|
||||
else
|
||||
now = now32();
|
||||
|
||||
K = PR_MIN(MAX_K, mNumAccesses);
|
||||
if (!K) {
|
||||
mProfit = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute time, in seconds, since k'th most recent access
|
||||
double timeSinceKthAccess = now - mAccessTime[K - 1];
|
||||
if (timeSinceKthAccess <= 0.0) // Sanity check
|
||||
timeSinceKthAccess = 1.0;
|
||||
|
||||
// Estimate frequency of future document access based on past
|
||||
// access frequency
|
||||
double frequencyAccess = K / timeSinceKthAccess;
|
||||
|
||||
// If we don't have much historical data on access frequency
|
||||
// use a heuristic based on document size as an estimate
|
||||
if (mLogicalLength) {
|
||||
if (K == 1) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
|
||||
} else if (K == 2) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate likelihood that data in cache is fresh, i.e.
|
||||
// that it corresponds to the document on the server
|
||||
double probabilityFreshness;
|
||||
PRInt32 halfLife, age, docTime;
|
||||
PRBool potentiallyStale;
|
||||
|
||||
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
|
||||
age = now - docTime;
|
||||
|
||||
probabilityFreshness = 1.0; // Optimistic
|
||||
|
||||
if (GetFlag(EXPIRATION_KNOWN)) {
|
||||
potentiallyStale = now > mExpirationTime;
|
||||
halfLife = mExpirationTime - mLastModifiedTime;
|
||||
} else if (GetFlag(STALE_TIME_KNOWN)) {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = mStaleTime - docTime;
|
||||
} else {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = TYPICAL_HALFLIFE;
|
||||
}
|
||||
|
||||
if (potentiallyStale) {
|
||||
if (halfLife < MIN_HALFLIFE)
|
||||
halfLife = MIN_HALFLIFE;
|
||||
|
||||
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
|
||||
}
|
||||
|
||||
mProfit = (float)(frequencyAccess * probabilityFreshness);
|
||||
if (mDownloadRate)
|
||||
mProfit /= mDownloadRate;
|
||||
}
|
||||
|
||||
// Number of entries to grow mRankedEntries array when it's full
|
||||
#define STATS_GROWTH_INCREMENT 256
|
||||
|
||||
|
||||
// Sorting predicate for NS_Quicksort
|
||||
int
|
||||
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
|
||||
{
|
||||
nsCachedNetData* entryA = *(nsCachedNetData**)a;
|
||||
nsCachedNetData* entryB = *(nsCachedNetData**)b;
|
||||
|
||||
// Percolate deleted or empty entries to the end of the mRankedEntries
|
||||
// array, so that they can be recycled.
|
||||
if (!entryA || entryA->GetFlag(RECYCLED)) {
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return -1;
|
||||
|
||||
// Evicted entries (those with no content data) and active entries (those
|
||||
// currently being updated) are collected towards the end of the sorted
|
||||
// array just prior to the deleted cache entries, since evicted entries
|
||||
// can't be re-evicted.
|
||||
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return -1;
|
||||
|
||||
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
|
||||
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
|
||||
|
||||
// Order cache entries by the number of times they've been accessed
|
||||
if (Ka < Kb)
|
||||
return -1;
|
||||
if (Ka > Kb)
|
||||
return +1;
|
||||
|
||||
/*
|
||||
* Among records that have been accessed an equal number of times, order
|
||||
* them by profit.
|
||||
*/
|
||||
if (entryA->mProfit > entryB->mProfit)
|
||||
return +1;
|
||||
if (entryA->mProfit < entryB->mProfit)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank cache entries in terms of their elegibility for eviction.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::RankRecords()
|
||||
{
|
||||
PRUint32 i, now;
|
||||
|
||||
// Add all cache records if this is the first ranking
|
||||
if (!mLastRankTime) {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
rv = AddAllRecordsInCache(cacheInfo->mCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
now = now32();
|
||||
|
||||
// Recompute profit for every known cache record, except deleted ones
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
nsCachedNetData* entry = mRankedEntries[i];
|
||||
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
entry->ComputeProfit(now);
|
||||
}
|
||||
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
|
||||
nsCachedNetData::Compare, 0);
|
||||
|
||||
mNumEntries -= mRecordsRemovedSinceLastRanking;
|
||||
mRecordsRemovedSinceLastRanking = 0;
|
||||
mLastRankTime = now;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// A heuristic policy to avoid the cost of re-ranking cache records by
|
||||
// profitability every single time space must be made available in the cache.
|
||||
void
|
||||
nsReplacementPolicy::MaybeRerankRecords()
|
||||
{
|
||||
// Rank at most once per minute
|
||||
PRUint32 now = now32();
|
||||
if ((now - mLastRankTime) >= 60)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
void
|
||||
nsReplacementPolicy::CompactRankedEntriesArray()
|
||||
{
|
||||
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::CheckForTooManyCacheEntries()
|
||||
{
|
||||
if (mCapacityRankedEntriesArray == mMaxEntries) {
|
||||
return DeleteOneEntry(0);
|
||||
} else {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 numEntries, maxEntries;
|
||||
|
||||
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numEntries == maxEntries)
|
||||
return DeleteOneEntry(cacheInfo->mCache);
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new association between a low-level cache database record and a
|
||||
* cache entry. Add the entry to the set of entries eligible for eviction from
|
||||
* the cache. This would typically be done when the cache entry is created.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsCachedNetData* cacheEntry;
|
||||
nsresult rv;
|
||||
|
||||
// First, see if the record is already known to the replacement policy
|
||||
PRInt32 recordID;
|
||||
rv = aRecord->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
|
||||
if (cacheEntry) {
|
||||
if (aResult) {
|
||||
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
|
||||
cacheEntry->Resurrect(aRecord);
|
||||
NS_ADDREF(cacheEntry);
|
||||
*aResult = cacheEntry;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compact the array of cache entry statistics, so that free entries appear
|
||||
// at the end, for possible reuse.
|
||||
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
|
||||
CompactRankedEntriesArray();
|
||||
|
||||
// If compaction doesn't yield available entries in the
|
||||
// mRankedEntries array, then extend the array.
|
||||
if (mNumEntries == mCapacityRankedEntriesArray) {
|
||||
PRUint32 newCapacity;
|
||||
|
||||
rv = CheckForTooManyCacheEntries();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
|
||||
if (newCapacity > mMaxEntries)
|
||||
newCapacity = mMaxEntries;
|
||||
|
||||
nsCachedNetData** newRankedEntriesArray;
|
||||
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
|
||||
newRankedEntriesArray =
|
||||
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
|
||||
if (!newRankedEntriesArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mRankedEntries = newRankedEntriesArray;
|
||||
mCapacityRankedEntriesArray = newCapacity;
|
||||
|
||||
PRUint32 i;
|
||||
for (i = mNumEntries; i < newCapacity; i++)
|
||||
mRankedEntries[i] = 0;
|
||||
}
|
||||
|
||||
// Recycle the record after the last in-use record in the array
|
||||
nsCachedNetData *entry = mRankedEntries[mNumEntries];
|
||||
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
|
||||
"Only deleted cache entries should appear at end of array");
|
||||
|
||||
if (!entry) {
|
||||
entry = new(mArena) nsCachedNetData;
|
||||
if (!entry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mRankedEntries[mNumEntries] = entry;
|
||||
} else {
|
||||
// Clear out recycled data structure
|
||||
nsCRT::zero(entry, sizeof(*entry));
|
||||
}
|
||||
|
||||
entry->Init(aRecord, aCache);
|
||||
AddCacheEntry(entry, recordID);
|
||||
|
||||
// Add one reference to the cache entry from the cache manager
|
||||
NS_ADDREF(entry);
|
||||
|
||||
if (aResult) {
|
||||
// And one reference from our caller
|
||||
NS_ADDREF(entry);
|
||||
*aResult = entry;
|
||||
}
|
||||
|
||||
mNumEntries++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
|
||||
getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return AssociateCacheEntryWithRecord(record, aCache, aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable record from the cache database. This is used
|
||||
* when the addition of another record would exceed either the cache manager or
|
||||
* the cache's maximum permitted number of records.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsresult rv;
|
||||
nsCachedNetData *entry;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
MaybeRerankRecords();
|
||||
for (; i < mNumEntries; i++) {
|
||||
entry = mRankedEntries[i];
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
continue;
|
||||
if (!aCache || (entry->mCache == aCache))
|
||||
break;
|
||||
}
|
||||
|
||||
// Report error if no record found to delete
|
||||
if (i == mNumEntries)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = entry->Delete();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = DeleteCacheEntry(entry);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
|
||||
{
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
*aStorageInUse = 0;
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 cacheStorage;
|
||||
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aStorageInUse += cacheStorage;
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable records from the cache until the occupancy of the
|
||||
* cache has been reduced by the given number of KB. This is used when the
|
||||
* addition of more cache data would exceed the cache's capacity.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsCachedNetData *entry;
|
||||
nsresult rv;
|
||||
PRUint32 occupancy;
|
||||
PRInt32 truncatedLength;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
MaybeRerankRecords();
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
rv = GetStorageInUse(&occupancy);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
if (occupancy <= aTargetOccupancy)
|
||||
return NS_OK;
|
||||
|
||||
entry = mRankedEntries[i];
|
||||
|
||||
// Skip deleted/empty cache entries and ones that have already been evicted
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
|
||||
continue;
|
||||
|
||||
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
|
||||
rv = entry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
PRUint32 contentLength;
|
||||
rv = record->GetStoredContentLength(&contentLength);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
// Additional cache storage required, in KB
|
||||
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
|
||||
|
||||
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
|
||||
if (truncatedLength < 0)
|
||||
truncatedLength = 0;
|
||||
} else {
|
||||
truncatedLength = 0;
|
||||
}
|
||||
rv = entry->Evict(truncatedLength);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class manages one or more caches that share a storage resource, e.g. a
|
||||
* file cache and a flat-database cache might each occupy space on the disk and
|
||||
* they would share a single instance of nsReplacementPolicy. The replacement
|
||||
* policy heuristically chooses which cache entries to evict when storage is
|
||||
* required to accommodate incoming cache data.
|
||||
*/
|
||||
|
||||
#ifndef _nsReplacementPolicy_h_
|
||||
#define _nsReplacementPolicy_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsIArena.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class nsCachedNetData;
|
||||
struct PL_HashTable;
|
||||
|
||||
/**
|
||||
* This private class is responsible for implementing the network data cache's
|
||||
* replacement policy, i.e. it decides which cache data should be evicted to
|
||||
* make room for new incoming data.
|
||||
*/
|
||||
class nsReplacementPolicy {
|
||||
|
||||
public:
|
||||
|
||||
nsReplacementPolicy();
|
||||
~nsReplacementPolicy();
|
||||
|
||||
protected:
|
||||
|
||||
nsresult Init(PRUint32 aMaxCacheEntries);
|
||||
nsresult AddCache(nsINetDataCache *aCache);
|
||||
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
nsresult GetStorageInUse(PRUint32* aNumKBytes);
|
||||
|
||||
friend class nsCacheManager;
|
||||
|
||||
private:
|
||||
nsresult RankRecords();
|
||||
void MaybeRerankRecords();
|
||||
void CompactRankedEntriesArray();
|
||||
nsresult DeleteOneEntry(nsINetDataCache* aCache);
|
||||
nsresult Evict(PRUint32 aTargetOccupancy);
|
||||
|
||||
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
|
||||
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
|
||||
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
|
||||
PRUint32 HashRecordID(PRInt32 aRecordID);
|
||||
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
|
||||
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
|
||||
nsresult CheckForTooManyCacheEntries();
|
||||
|
||||
class CacheInfo;
|
||||
|
||||
private:
|
||||
|
||||
// Growable array of pointers to individual cache entries; It is sorted by
|
||||
// profitability, such that low-numbered array indices refer to cache
|
||||
// entries that are the least profitable to retain. New cache entries are
|
||||
// added to the end of the array. Deleted cache entries are specially
|
||||
// marked and percolate to the end of the array for recycling whenever
|
||||
// mRankedEntries is sorted. Evicted cache entries (those with no
|
||||
// associated content data) are retained for the purpose of improving the
|
||||
// replacement policy efficacy, and are percolated towards the end of the
|
||||
// array, just prior to the deleted cache entries.
|
||||
//
|
||||
// The array is not in sorted order 100% of the time; For efficiency
|
||||
// reasons, sorting is only done when heuristically deemed necessary.
|
||||
nsCachedNetData** mRankedEntries;
|
||||
|
||||
// Hash table buckets to map Record ID to cache entry. We use this instead
|
||||
// of a PL_HashTable to reduce storage requirements
|
||||
nsCachedNetData** mMapRecordIdToEntry;
|
||||
|
||||
// Length of mMapRecordIdToEntry array
|
||||
PRUint32 mHashArrayLength;
|
||||
|
||||
// Linked list of caches that share this replacement policy
|
||||
CacheInfo* mCaches;
|
||||
|
||||
// Allocation area for cache entry (nsCachedNetData) instances
|
||||
nsCOMPtr<nsIArena> mArena;
|
||||
|
||||
// Bookkeeping
|
||||
PRUint32 mRecordsRemovedSinceLastRanking;
|
||||
|
||||
// Maximum permitted length of mRankedEntries array
|
||||
PRUint32 mMaxEntries;
|
||||
|
||||
// Number of occupied slots in mRankedEntries array
|
||||
PRUint32 mNumEntries;
|
||||
|
||||
// Capacity of mRankedEntries array
|
||||
PRUint32 mCapacityRankedEntriesArray;
|
||||
|
||||
// Time at which cache entries were last ranked by profitability
|
||||
PRUint32 mLastRankTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // _nsReplacementPolicy_h_
|
||||
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsICachedNetData.idl \
|
||||
nsINetDataCacheManager.idl \
|
||||
nsINetDataCache.idl \
|
||||
nsINetDataCacheRecord.idl \
|
||||
nsINetDataDiskCache.idl \
|
||||
nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
DEPTH = ..\..\..
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
.\nsICachedNetData.idl \
|
||||
.\nsINetDataCacheManager.idl \
|
||||
.\nsINetDataCache.idl \
|
||||
.\nsINetDataCacheRecord.idl \
|
||||
.\nsINetDataDiskCache.idl \
|
||||
.\nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIURI;
|
||||
interface nsIObserver;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsILoadGroup;
|
||||
interface nsIStreamListener;
|
||||
|
||||
/**
|
||||
* The nsICachedNetData interface represents a single entry in a database that
|
||||
* caches data retrieved from the network. This interface is implemented by the
|
||||
* cache manager on top of the low-level nsINetDataCacheRecord and
|
||||
* nsINetDataCache interfaces that are implemented by the database.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is stored as a byte array. Each entry in the
|
||||
* cache is indexed by two different keys: a record id number and a key created
|
||||
* by combining the URI with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* @See nsINetDataCacheRecord
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
|
||||
interface nsICachedNetData : nsISupports
|
||||
{
|
||||
/**
|
||||
* String form of the URI provided as an argument to the call to
|
||||
* nsINetDataCacheManager::GetCachedNetData() that created this record.
|
||||
*/
|
||||
readonly attribute string uriSpec;
|
||||
|
||||
/**
|
||||
* Getter for the opaque secondary database key provided as an argument to
|
||||
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
|
||||
* record.
|
||||
*/
|
||||
void getSecondaryKey(out unsigned long length,
|
||||
[retval, size_is(length)] out string secondaryKey);
|
||||
|
||||
/**
|
||||
* This flag may be set by a protocol handler to indicate that it supports
|
||||
* partial fetching of data. In that case, the cache manager is permitted
|
||||
* to truncate the entry's content to accommodate incoming data for other
|
||||
* cache entries rather than deleting it wholesale.
|
||||
*/
|
||||
attribute boolean allowPartial;
|
||||
|
||||
/**
|
||||
* This flag indicates that the write stream supplying content data for the
|
||||
* cache did not complete normally and, therefore, the content may be
|
||||
* truncated.
|
||||
*/
|
||||
readonly attribute boolean partialFlag;
|
||||
|
||||
/**
|
||||
* This flag can be set and cleared by a protocol handler as a form of
|
||||
* self-notification, so as to avoid race conditions in which a protocol
|
||||
* handler issues two identical network requests to fill the same cache
|
||||
* entry. The cache manager itself largely ignores this flag.
|
||||
*/
|
||||
attribute boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* inUse is set if any existing channels are associated with this cache
|
||||
* entry or if the updateInProgess flag is set. This can be used to
|
||||
* prevent writing to a cache entry by a protocol handler if it's being
|
||||
* read or written elsewhere.
|
||||
*/
|
||||
readonly attribute boolean inUse;
|
||||
|
||||
/**
|
||||
* Date/time that the document was last stored on the origin server, as
|
||||
* supplied by the protocol handler. This value is used as input to the
|
||||
* cache replacement policy, i.e. it is not used for validation. If the
|
||||
* protocol can't supply a last-modified time, this attribute should remain
|
||||
* unset. When unset, the value of this attribute is zero.
|
||||
*
|
||||
* FIXME: Should use nsIDateTime interface, once it's created
|
||||
* instead of PRTime, for improved scriptability ?
|
||||
*/
|
||||
attribute PRTime lastModifiedTime;
|
||||
|
||||
/**
|
||||
* Supplied by the protocol handler, the expirationTime attribute specifies
|
||||
* the time until which the document is guaranteed fresh, i.e. the document
|
||||
* does not have to be validated with the server and, therefore, any data
|
||||
* in cache is definitely usable. The value of this attribute serves as a
|
||||
* hint to the cache replacement policy. Only one of either staleTime or
|
||||
* expirationTime may be set for a single cache record. When unset, the
|
||||
* value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime expirationTime;
|
||||
|
||||
/**
|
||||
* Date/time supplied by the protocol handler, at which point the content
|
||||
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
|
||||
* with respect to the data on the server. This heuristic date does not
|
||||
* necessarily correspond to the HTTP Expires header, as it does not
|
||||
* determine when cached network data must be validated with the origin
|
||||
* server, but only serves as a hint to the cache replacement policy. Only
|
||||
* one of either staleTime or expirationTime may be set for a single cache
|
||||
* record. When unset, the value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime staleTime;
|
||||
|
||||
/**
|
||||
* Date/time of last access of the data in this cache record, as determined
|
||||
* by the cache manager.
|
||||
*/
|
||||
readonly attribute PRTime lastAccessTime;
|
||||
|
||||
/**
|
||||
* Number of times this record has been accessed since it was first stored.
|
||||
*/
|
||||
readonly attribute PRUint16 numberAccesses;
|
||||
|
||||
/**
|
||||
* Accessor methods for opaque meta-data which can be read and updated
|
||||
* independently of the content data.
|
||||
*
|
||||
* The aTag argument can be used to accommodate multiple clients of the
|
||||
* cache API, each of which wants to store its own private meta-data into
|
||||
* the cache. For example, there could be a "headers" tag that the HTTP
|
||||
* protocol handler uses to store http response headers and a "image size"
|
||||
* tag used to store the image dimensions of a GIF file. The aData
|
||||
* argument refers to an opaque blob of arbitrary bytes.
|
||||
*
|
||||
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
|
||||
* string, the contents of aData must be byte-swapped by the,
|
||||
* caller, so as to make the cache files endian-independent.
|
||||
*/
|
||||
void getAnnotation(in string aTag,
|
||||
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
|
||||
void setAnnotation(in string aTag,
|
||||
in PRUint32 aLength, [size_is(aLength)] in string aData);
|
||||
|
||||
/**
|
||||
* As a getter, return the number of content bytes stored in the cache,
|
||||
* i.e. via the nsIChannel streaming APIs. This may be less than the
|
||||
* complete content length if a partial cache fill occurred. The cached
|
||||
* content can be truncated by setting the value of this attribute. The
|
||||
* value of the attribute represents a logical, not a physical, length. If
|
||||
* compression has been used, the content may consume less storage than
|
||||
* indicated by this attribute.
|
||||
*
|
||||
* When this attribute is set to zero the associated cache disk file, if
|
||||
* any, should be deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Notify any observers associated with this cache entry of the deletion
|
||||
* request. If all observers drop their reference to the cache entry,
|
||||
* proceed to delete the underlying cache database record and associated
|
||||
* content storage.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Flush any changes in this entry's data to the cache database. This
|
||||
* method will automatically be called when the last reference to the cache
|
||||
* is dropped, but it can also be called explicitly for a synchronous
|
||||
* effect.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Parent container cache for this entry.
|
||||
*/
|
||||
readonly attribute nsINetDataCache cache;
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. It is expected that many of the nsIChannel methods return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*
|
||||
* Though nsIChannel provides for both async and synchronous I/O APIs, both
|
||||
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
|
||||
* required. The aProxyChannel argument allows another channel to be
|
||||
* specified as the proffered argument to nsIStreamListener methods rather
|
||||
* than the cache's own channel.
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
|
||||
in nsIChannel aProxyChannel);
|
||||
|
||||
/**
|
||||
* This method can be used by a caching protocol handler to store data in
|
||||
* the cache by forking an asynchronous read stream so that it is
|
||||
* simultaneously sent to a requester and written into the cache. This
|
||||
* method implicitly sets the updateInProgress flag, if it has not already
|
||||
* been set.
|
||||
*/
|
||||
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
|
||||
in PRUint32 aStartOffset);
|
||||
};
|
||||
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The nsINetDataCache defines the low-level API for a network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* This interface, along with nsINetDataCacheRecord, is implemented by
|
||||
* the memory cache, the file cache and, optionally, by some extension
|
||||
* caches. This interface is essentially a pseudo-private API for the
|
||||
* cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by two
|
||||
* different keys: a record id number and a key created by combining the URI
|
||||
* with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* The nsINetDataCache interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The
|
||||
* memory cache, any disk caches and any extension caches must all
|
||||
* implement this interface.
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCache : nsISupports
|
||||
{
|
||||
/**
|
||||
* Human-readable description of the cache module, e.g. "Disk Cache"
|
||||
*/
|
||||
readonly attribute wstring description;
|
||||
|
||||
/**
|
||||
* Returns true if cached data is available for the given opaque key,
|
||||
* even if only partial data is stored.
|
||||
*/
|
||||
boolean contains([size_is(length)] in string key, in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given opaque key. If one does not
|
||||
* exist, create a new, empty record.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
|
||||
in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI using the record ID as a key.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
|
||||
|
||||
/**
|
||||
* False indicates that this cache is entirely bypassed.
|
||||
*/
|
||||
attribute boolean enabled;
|
||||
|
||||
/**
|
||||
* Constants for flags attribute, below
|
||||
*/
|
||||
|
||||
// Used for extension caches, e.g. a CD-ROM cache
|
||||
const long READ_ONLY = 1 << 0;
|
||||
|
||||
// One of these bits must be set
|
||||
const long MEMORY_CACHE = 1 << 1;
|
||||
const long FLAT_FILE_CACHE = 1 << 2;
|
||||
const long FILE_PER_URL_CACHE = 1 << 3;
|
||||
|
||||
/**
|
||||
* See constants defined above.
|
||||
*/
|
||||
readonly attribute PRUint32 flags;
|
||||
|
||||
/**
|
||||
* Total number of URI entries stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Maximum number of URI entries that may be stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 maxEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the URI entries stored in the cache.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/**
|
||||
* Contains a reference to the next cache in search order. For the memory
|
||||
* cache, this attribute always references the disk cache. For the disk
|
||||
* cache, it contains a reference to the first extension cache.
|
||||
*/
|
||||
attribute nsINetDataCache nextCache;
|
||||
|
||||
/**
|
||||
* An estimate of the amount of storage occupied by the cache, in kB.
|
||||
* Actual use may be slightly higher than reported due to cache overhead
|
||||
* and heap fragmentation (in the memory cache) or block quantization (in
|
||||
* the disk cache).
|
||||
*/
|
||||
readonly attribute PRUint32 storageInUse;
|
||||
|
||||
/**
|
||||
* Remove all entries from a writable cache. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the cache's Capacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void removeAll();
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
|
||||
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
|
||||
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
|
||||
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
|
||||
%}
|
||||
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsICachedNetData;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataDiskCache;
|
||||
interface nsIURI;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The network-response cache manager is partly responsible for the caching of
|
||||
* content and associated metadata that has been retrieved via the network.
|
||||
* (The remaining responsibility for caching lies with individual network
|
||||
* protocol handlers.)
|
||||
*
|
||||
* The cache manager supervises the actions of individual cache components,
|
||||
* such as the memory cache, the disk cache and any extension caches, e.g. a
|
||||
* read-only CD-ROM cache.
|
||||
*
|
||||
* @See nsINetDataCache
|
||||
* @See nsICachedNetData
|
||||
*/
|
||||
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCacheManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the memory cache is
|
||||
* neither searched nor will any data be stored into it. This might be
|
||||
* appropriate, for example, with images, because they have their own
|
||||
* cache for storing *decoded* images.
|
||||
*/
|
||||
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the disk cache
|
||||
* is neither searched nor will any be data stored into it.
|
||||
* However, read-only extension caches may be searched. This
|
||||
* might be used to avoid leaving persistent records of secure
|
||||
* data.
|
||||
*/
|
||||
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, any stream
|
||||
* content is stored in the cache as a single disk file. Content
|
||||
* will not be cached in the memory cache nor is it cached in a
|
||||
* flat-file cache database. This is used to implement the jar
|
||||
* protocol handler and to provide the stream-as-file semantics
|
||||
* required by the classic bowser plugin API.
|
||||
*/
|
||||
const unsigned long CACHE_AS_FILE = 1 << 2;
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI. If one does not exist,
|
||||
* create a new, empty record. The normal search order for caches is:
|
||||
* + Memory cache
|
||||
* + Disk cache
|
||||
* + File cache (stream-as-file cache)
|
||||
* + All extension caches
|
||||
*
|
||||
* When writing, data is typically stored in both the memory cache and the
|
||||
* disk cache. Both the search order and this write policy can be modified by
|
||||
* setting one or more of the flag argument bits, as defined above.
|
||||
*
|
||||
* The optionally-NULL secondaryKey argument can be used, e.g. for form
|
||||
* post data or for HTTP headers in the case of HTTP.
|
||||
*/
|
||||
nsICachedNetData getCachedNetData(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Returns true if cached content is available for the given URI, even if
|
||||
* only partial data is stored. The flags argument behaves the same as for
|
||||
* the GetCachedNetData() method, above.
|
||||
*/
|
||||
boolean contains(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Total number of unexpired URI entries stored in all caches. This number
|
||||
* does not take into account duplicate URIs, e.g. because the memory cache
|
||||
* and the disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
|
||||
* be enumerated more than once, e.g. because the the memory cache and the
|
||||
* disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/*
|
||||
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
|
||||
* The first module enumerated will be the memory cache, the second will be
|
||||
* the disk cache, then the file cache, followed by all the extension
|
||||
* caches, in search order.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheModuleIterator();
|
||||
|
||||
/**
|
||||
* Remove all entries from all writable caches. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the DiskCacheCapacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void RemoveAll();
|
||||
|
||||
/**
|
||||
* The disk cache is made up of the file cache (for stream-as-file
|
||||
* requests) and a (possibly independent) persistent cache that handles all
|
||||
* other cache requests. This attribute sets/gets the combined capacity of
|
||||
* these caches, measured in KBytes. Setting the capacity lower than the
|
||||
* current amount of space currently in use may cause cache entries to be
|
||||
* evicted from the cache to accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 diskCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute sets/gets the capacity of the memory cache, measured in
|
||||
* KBytes. Setting the capacity lower than the current amount of space
|
||||
* currently in use may cause cache entries to be evicted from the cache to
|
||||
* accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 memCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute must be set before attempting to store into the disk cache.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
|
||||
%}
|
||||
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsrootidl.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
|
||||
/**
|
||||
* The nsINetDataCacheRecord represents a single entry in a database that
|
||||
* caches data retrieved from the network. On top of this low-level interface
|
||||
* to the raw record data, the cache manager implements a higher-level record
|
||||
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
|
||||
* (internally) associated with a parent database, an instance of the
|
||||
* nsINetDataCache interface. This interface is essentially a pseudo-private
|
||||
* API for the cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is accessed as a contiguous byte array. Each
|
||||
* entry in the cache is indexed by two different keys: a unique record id
|
||||
* number, generated by the cache, and an opaque string. The latter contains
|
||||
* the URI and other secondary key information, e.g. HTTP form post key/value
|
||||
* pairs.
|
||||
*
|
||||
* The nsINetDataCacheRecord interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The memory cache,
|
||||
* the disk cache, a flat-file cache and any read-only extension caches must
|
||||
* all implement this interface.
|
||||
*
|
||||
* @See nsICachedNetData
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
|
||||
interface nsILoadGroup;
|
||||
|
||||
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
|
||||
interface nsINetDataCacheRecord : nsISupports
|
||||
{
|
||||
/**
|
||||
* As far as the nsINetDataCacheRecord implementation is concerned, the
|
||||
* cache entry database key is an opaque blob, but it's intended to contain
|
||||
* both the URI and any secondary keys, such as HTTP post data.
|
||||
*/
|
||||
void getKey(out unsigned long length, [size_is(length), retval] out string key);
|
||||
|
||||
/**
|
||||
* A persistent record number assigned by the cache which must be unique
|
||||
* among all entries stored within the same cache. The record ID serves as
|
||||
* an alternate key to the cache record. Providing that they satisfy the
|
||||
* afforementioned uniqueness requirement, record IDs can be assigned any
|
||||
* value by the database except that they may never be zero.
|
||||
*/
|
||||
readonly attribute PRInt32 recordID;
|
||||
|
||||
/**
|
||||
* Opaque data which can be updated for each cache entry independently of
|
||||
* the content data. This data is a combination of protocol-independent
|
||||
* data provided by the cache manager and protocol-specific meta-data,
|
||||
* e.g. HTTP headers.
|
||||
*/
|
||||
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
|
||||
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
|
||||
|
||||
/**
|
||||
* Number of content bytes stored in the cache, i.e. via the nsIChannel
|
||||
* streaming APIs. This may be less than the complete content length if a
|
||||
* partial cache fill occurred. Additionally, the cached content can be
|
||||
* truncated by reducing the value of this attribute. When this attribute
|
||||
* is set to zero the associated cache disk file, if any, should be
|
||||
* deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Delete this cache entry and its associated content.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. However, many of the nsIChannel methods may return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup loadGroup);
|
||||
|
||||
/**
|
||||
* If a cache is implemented such that it stores each URI's content in an
|
||||
* individual disk file, this method will identify the file corresponding
|
||||
* to this record. This may be used to implement the "stream-as-file"
|
||||
* semantics required by some plugins and by the 'jar:' protocol handler.
|
||||
* However, not all cache implementations are *required* to store the data
|
||||
* from each URI in an individual file, so it is acceptable for an
|
||||
* implementation of this method to signal NS_NOT_IMPLEMENTED.
|
||||
*/
|
||||
readonly attribute nsIFileSpec filename;
|
||||
};
|
||||
42
mozilla/netwerk/cache/public/nsINetDataDiskCache.idl
vendored
Normal file
42
mozilla/netwerk/cache/public/nsINetDataDiskCache.idl
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsINetDataCache.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A network-data disk cache is used to persistently cache the responses to
|
||||
* network retrieval commands. Each cache entry may contain both content,
|
||||
* e.g. GIF image data, and associated metadata, e.g. HTTP headers.
|
||||
*/
|
||||
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
|
||||
interface nsINetDataDiskCache : nsINetDataCache
|
||||
{
|
||||
/**
|
||||
* This attribute must be set before calling any other methods of this
|
||||
* interface.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIStreamAsFileObserver;
|
||||
|
||||
/**
|
||||
* In addition to enhancing effective network response time via caching, the
|
||||
* cache manager serves a second purpose by providing the stream-as-file
|
||||
* service required by traditional browser plugins and the jar: protocol
|
||||
* handler. The interface below provides a means for a client to determine the
|
||||
* filename associated with a stream and to detect modification/deletion of
|
||||
* that file.
|
||||
*/
|
||||
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFile : nsISupports
|
||||
{
|
||||
/**
|
||||
* Filename containing stream-as-file
|
||||
*/
|
||||
readonly attribute nsIFileSpec fileSpec;
|
||||
|
||||
/**
|
||||
* Add an observer for this cache record. When the cache wants to delete
|
||||
* or truncate a record, so as to make space for another cache entry's
|
||||
* content data, it will call <code>aObserver</code>'s Observe() method,
|
||||
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
|
||||
* argument and an appropriate message. If the observer does not wish to
|
||||
* inhibit deletion/truncation, it should Release() any references it has to the
|
||||
* cache record.
|
||||
*
|
||||
* @See nsIStreamAsFileObserver
|
||||
*/
|
||||
void addObserver(in nsIStreamAsFileObserver aObserver);
|
||||
|
||||
/**
|
||||
* Delete an observer that was added by the AddObserver() method.
|
||||
*/
|
||||
void removeObserver(in nsIStreamAsFileObserver aObserver);
|
||||
};
|
||||
|
||||
/**
|
||||
* This interface can be implemented by a client to receive notifications of
|
||||
* either modification or deletion of a file created by the cache manager using
|
||||
* the stream-as-file semantics.
|
||||
*/
|
||||
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFileObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag bits for argument to Observe() method.
|
||||
*/
|
||||
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
|
||||
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
|
||||
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
|
||||
const long INVALIDATE = 1 << 3; // File is out-of-date
|
||||
|
||||
// Convenience value
|
||||
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
|
||||
|
||||
/**
|
||||
* Receive either a notification or a request concerning a file that has
|
||||
* been opened using stream-as-file. The aMessage and aError arguments
|
||||
* have varying values depending on the nature of the notification.
|
||||
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
|
||||
* and stored on disk in a file. At that point, and no sooner, may the
|
||||
* filename attribute of the associated nsIStreamAsFile be accessed via the
|
||||
* associated nsIStreamAsFile interface. If the aMessage argument is
|
||||
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
|
||||
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
|
||||
* the callee should immediately Release() all references to the
|
||||
* nsIStreamAsFile (and any references to its associated nsICachedNetData
|
||||
* instances), unless it wishes to inhibit the requested file modification.
|
||||
* If the aMessage argument is INVALIDATE, the cache manager is replacing
|
||||
* the file with a more recent version. If a client wants to continue
|
||||
* using the (now out-of-date) file, it must delete it when it has finished,
|
||||
* as the cache manager will effectively relinquished ownership of the
|
||||
* file.
|
||||
*/
|
||||
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
|
||||
in PRUint32 aMessage,
|
||||
in nsresult aError);
|
||||
};
|
||||
39
mozilla/netwerk/makefile.win
Normal file
39
mozilla/netwerk/makefile.win
Normal file
@@ -0,0 +1,39 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH = ..
|
||||
|
||||
MODULE = necko
|
||||
|
||||
DIRS= \
|
||||
base \
|
||||
dns \
|
||||
build \
|
||||
protocol \
|
||||
socket \
|
||||
util \
|
||||
mime \
|
||||
streamconv \
|
||||
cache \
|
||||
test \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
32
mozilla/netwerk/protocol/http/public/nsIHTTPHeader.idl
Normal file
32
mozilla/netwerk/protocol/http/public/nsIHTTPHeader.idl
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIAtom;
|
||||
|
||||
[scriptable, uuid(a3ec67f0-465a-11d3-9a89-0080c7cb1080)]
|
||||
interface nsIHTTPHeader : nsISupports
|
||||
{
|
||||
nsIAtom GetField();
|
||||
string GetValue();
|
||||
};
|
||||
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsICachedNetData.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
// FIXME - temporary
|
||||
#define NUM_CACHE_ENTRIES 25
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Limits, converted to KB
|
||||
#define DISK_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 4) >> 10)
|
||||
#define MEM_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 3) >> 10)
|
||||
|
||||
// Length of random-data cache entry URI key
|
||||
#define CACHE_KEY_LENGTH 13
|
||||
|
||||
// Length of random-data cache entry secondary key
|
||||
#define CACHE_SECONDARY_KEY_LENGTH 10
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_PROTOCOL_PRIVATE_LENGTH 10
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void ReadString(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual PRBool MatchString(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
virtual void SkipString(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345 ^ (mState >> 16);
|
||||
return mState;
|
||||
}
|
||||
|
||||
PRUint8 NextChar() {
|
||||
PRUint8 c;
|
||||
do {
|
||||
c = Next();
|
||||
} while (!isalnum(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as Read(), but using only printable chars and
|
||||
// with a terminating NUL
|
||||
void ReadString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = NextChar();
|
||||
}
|
||||
*aBuf = 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
MatchString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(NextChar() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Check for terminating NUL character
|
||||
if (*aBuf)
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
void
|
||||
SkipString(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
NextChar();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalBytesWritten = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
//FIXME NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
// "Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsICachedNetData *cacheEntry, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
// FIXME NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
// "nsICachedNetData::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
|
||||
static PRUint32
|
||||
convertPRTimeToSeconds(PRTime aTime64)
|
||||
{
|
||||
double fpTime;
|
||||
LL_L2D(fpTime, aTime64);
|
||||
return (PRUint32)(fpTime * 1e-6 + 0.5);
|
||||
}
|
||||
|
||||
// Convert unix-style time_t, i.e. seconds since the epoch, to PRTime
|
||||
static PRTime
|
||||
convertSecondsToPRTime(PRUint32 aSeconds)
|
||||
{
|
||||
PRInt64 t64;
|
||||
LL_L2I(t64, aSeconds);
|
||||
LL_MUL(t64, t64, 1000000);
|
||||
return t64;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCacheManager *aCache, PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
RandomStream *randomStream;
|
||||
char uriCacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char *storedUriKey;
|
||||
PRUint32 testNum;
|
||||
|
||||
gTotalBytesRead = 0;
|
||||
gTotalDuration = 0;
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(uriCacheKey, sizeof uriCacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = aCache->Contains(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Test GetUriSpec() method
|
||||
rv = cacheEntry->GetUriSpec(&storedUriKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedUriKey, &uriCacheKey[0], sizeof uriCacheKey),
|
||||
"nsICachedNetData::GetKey failed");
|
||||
nsAllocator::Free(storedUriKey);
|
||||
|
||||
// Test GetSecondaryKey() method
|
||||
PRUint32 storedSecondaryKeyLength;
|
||||
char* storedSecondaryKey;
|
||||
rv = cacheEntry->GetSecondaryKey(&storedSecondaryKeyLength, &storedSecondaryKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedSecondaryKey, &secondaryCacheKey[0],
|
||||
sizeof secondaryCacheKey),
|
||||
"nsICachedNetData::GetSecondaryKey failed");
|
||||
|
||||
// Compare against stored protocol data
|
||||
char *storedProtocolData;
|
||||
PRUint32 storedProtocolDataLength;
|
||||
rv = cacheEntry->GetAnnotation("test data", &storedProtocolDataLength, &storedProtocolData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
storedProtocolDataLength == CACHE_PROTOCOL_PRIVATE_LENGTH,
|
||||
"nsICachedNetData::GetAnnotation() failed");
|
||||
randomStream->Match(storedProtocolData, storedProtocolDataLength);
|
||||
|
||||
// Test GetAllowPartial()
|
||||
PRBool allowPartial;
|
||||
rv = cacheEntry->GetAllowPartial(&allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(allowPartial == (PRBool)(randomStream->Next() & 1)),
|
||||
"nsICachedNetData::GetAllowPartial() failed");
|
||||
|
||||
// Test GetExpirationTime()
|
||||
PRTime expirationTime;
|
||||
PRTime expectedExpirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->GetExpirationTime(&expirationTime);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && LL_EQ(expirationTime, expectedExpirationTime),
|
||||
"nsICachedNetData::GetExpirationTime() failed");
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(cacheEntry, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
nsCOMPtr<nsINetDataCache> containingCache;
|
||||
char buf[1000];
|
||||
PRUint32 protocolDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char protocolData[CACHE_PROTOCOL_PRIVATE_LENGTH];
|
||||
PRUint32 testNum;
|
||||
RandomStream *randomStream;
|
||||
|
||||
gTotalBytesWritten = 0;
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(cacheKey, sizeof cacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access cacheEntry via cache key");
|
||||
|
||||
// Test nsINetDataCacheManager::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
char *protocolDatap;
|
||||
rv = cacheEntry->GetAnnotation("test data", &protocolDataLength, &protocolDatap);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((protocolDataLength != 0) || (protocolDatap != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(protocolData, sizeof protocolData);
|
||||
cacheEntry->SetAnnotation("test data", sizeof protocolData, protocolData);
|
||||
|
||||
// Store random data as allow-partial flag
|
||||
PRBool allowPartial = randomStream->Next() & 1;
|
||||
rv = cacheEntry->SetAllowPartial(allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetAllowPartial() failed");
|
||||
|
||||
// Store random data as expiration time
|
||||
PRTime expirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->SetExpirationTime(expirationTime);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetExpirationTime() failed");
|
||||
|
||||
// Cache manager complains if expiration set without setting last-modified time
|
||||
rv = cacheEntry->SetLastModifiedTime(expirationTime);
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetCache(getter_AddRefs(containingCache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
|
||||
PRUint32 storageInUse;
|
||||
rv = containingCache->GetStorageInUse(&storageInUse);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (storageInUse <= aCacheCapacity),
|
||||
"Cache manager failed to limit cache growth");
|
||||
}
|
||||
outStream->Close();
|
||||
gTotalBytesWritten += streamLength;
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Test(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(aCache, aFlags, aCacheCapacity);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(aCache, aFlags);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheManager> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_CACHE_MANAGER_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCacheManager),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create cache manager factory") ;
|
||||
|
||||
cache->SetDiskCacheCapacity(DISK_CACHE_CAPACITY);
|
||||
cache->SetMemCacheCapacity(MEM_CACHE_CAPACITY);
|
||||
|
||||
InitQueue();
|
||||
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE, MEM_CACHE_CAPACITY);
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_MEMORY_CACHE, DISK_CACHE_CAPACITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
@@ -0,0 +1,820 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
// file cache include
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
// file cache cid
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
PRUint32 afterContentLength;
|
||||
rv = record->GetStoredContentLength(&afterContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
NS_ASSERTION(afterContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::SetContentLength() failed to truncate record");
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
CounterStream *counterStream;
|
||||
int i;
|
||||
for (i = 0; i < 100; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
}
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 totalBytesWritten = 0;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
totalBytesWritten += streamLength;
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = totalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
totalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if(argc <2) {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
if (PL_strcasecmp(argv[1], "-m") == 0) {
|
||||
rv = nsComponentManager::CreateInstance(kMemCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
} else if (PL_strcasecmp(argv[1], "-f") == 0) {
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> diskcache ;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataDiskCache),
|
||||
getter_AddRefs(diskcache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create disk cache factory") ;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> folder ;
|
||||
NS_NewFileSpec(getter_AddRefs(folder)) ;
|
||||
folder->SetUnixStyleFilePath("/tmp") ;
|
||||
diskcache->SetDiskCacheFolder(folder) ;
|
||||
|
||||
cache = diskcache ;
|
||||
|
||||
} else {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
82
mozilla/netwerk/test/makefile.win
Normal file
82
mozilla/netwerk/test/makefile.win
Normal file
@@ -0,0 +1,82 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
MAKE_OBJ_TYPE = EXE
|
||||
PROG1 = .\$(OBJDIR)\TestFileInput.exe
|
||||
PROG2 = .\$(OBJDIR)\TestSocketInput.exe
|
||||
PROG3 = .\$(OBJDIR)\TestSocketIO.exe
|
||||
PROG4 = .\$(OBJDIR)\TestProtocols.exe
|
||||
PROG5 = .\$(OBJDIR)\TestSocketTransport.exe
|
||||
PROG6 = .\$(OBJDIR)\urltest.exe
|
||||
PROG7 = .\$(OBJDIR)\TestFileInput2.exe
|
||||
PROG8 = .\$(OBJDIR)\TestFileTransport.exe
|
||||
PROG9 = .\$(OBJDIR)\TestRes.exe
|
||||
PROGA = .\$(OBJDIR)\TestRawCache.exe
|
||||
PROGB = .\$(OBJDIR)\TestCacheMgr.exe
|
||||
PROGRAMS = \
|
||||
#$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(PROG7) $(PROG8) $(PROG9)\
|
||||
$(PROGA) $(PROGB)
|
||||
|
||||
LCFLAGS=-DUSE_NSREG -GX
|
||||
|
||||
REQUIRES=libreg
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\dist\include \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(PROGRAMS)
|
||||
-for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin
|
||||
|
||||
clobber::
|
||||
-for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p
|
||||
|
||||
$(PROG1): $(OBJDIR) TestFileInput.cpp
|
||||
|
||||
$(PROG2): $(OBJDIR) TestSocketInput.cpp
|
||||
|
||||
$(PROG3): $(OBJDIR) TestSocketIO.cpp
|
||||
|
||||
$(PROG4): $(OBJDIR) TestProtocols.cpp
|
||||
|
||||
$(PROG5): $(OBJDIR) TestSocketTransport.cpp
|
||||
|
||||
$(PROG6): $(OBJDIR) urltest.cpp
|
||||
|
||||
$(PROG7): $(OBJDIR) TestFileInput2.cpp
|
||||
|
||||
$(PROG8): $(OBJDIR) TestFileTransport.cpp
|
||||
|
||||
$(PROG9): $(OBJDIR) TestRes.cpp
|
||||
|
||||
$(PROGA): $(OBJDIR) TestRawCache.cpp
|
||||
|
||||
$(PROGB): $(OBJDIR) TestCacheMgr.cpp
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile
|
||||
# pkcs11c.c in 64-bit mode for unknown reasons. A workaround is
|
||||
# to compile it with optimizations turned on. (Bugzilla bug #63815)
|
||||
ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3)
|
||||
ifeq ($(USE_64),1)
|
||||
ifndef BUILD_OPT
|
||||
$(OBJDIR)/pkcs11.o: pkcs11.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ -c -O2 $(CFLAGS) $<
|
||||
$(OBJDIR)/pkcs11c.o: pkcs11c.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ -c -O2 $(CFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,107 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../freebl
|
||||
ifdef MOZILLA_SECURITY_BUILD
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../crypto
|
||||
endif
|
||||
|
||||
SQLITE_LIB = $(DIST)/lib/$(LIB_PREFIX)sqlite3.$(LIB_SUFFIX)
|
||||
ifdef NSS_USE_SYTEM_SQLITE
|
||||
SQLITE_LIB = -lsqlite3
|
||||
endif
|
||||
|
||||
EXTRA_LIBS += \
|
||||
$(CRYPTOLIB) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
|
||||
$(SQLITE_LIB) \
|
||||
$(NULL)
|
||||
|
||||
# can't do this in manifest.mn because OS_TARGET isn't defined there.
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
|
||||
# don't want the 32 in the shared library name
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
|
||||
|
||||
RES = $(OBJDIR)/$(LIBRARY_NAME).res
|
||||
RESNAME = $(LIBRARY_NAME).rc
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
else # ! NS_USE_GCC
|
||||
|
||||
EXTRA_SHARED_LIBS += \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
|
||||
$(NULL)
|
||||
endif # NS_USE_GCC
|
||||
|
||||
else
|
||||
|
||||
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
|
||||
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
OS_LIBS += -lbsm
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DDBM_USING_NSPR
|
||||
endif
|
||||
|
||||
# indicates dependency on freebl static lib
|
||||
$(SHARED_LIBRARY): $(CRYPTOLIB)
|
||||
@@ -1,641 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secoid.h"
|
||||
#include "secitem.h"
|
||||
#include "secerr.h"
|
||||
#include "ec.h"
|
||||
#include "ecl-curve.h"
|
||||
|
||||
#define CHECK_OK(func) if (func == NULL) goto cleanup
|
||||
#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
|
||||
|
||||
/*
|
||||
* Initializes a SECItem from a hexadecimal string
|
||||
*
|
||||
* Warning: This function ignores leading 00's, so any leading 00's
|
||||
* in the hexadecimal string must be optional.
|
||||
*/
|
||||
static SECItem *
|
||||
hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str)
|
||||
{
|
||||
int i = 0;
|
||||
int byteval = 0;
|
||||
int tmp = PORT_Strlen(str);
|
||||
|
||||
if ((tmp % 2) != 0) return NULL;
|
||||
|
||||
/* skip leading 00's unless the hex string is "00" */
|
||||
while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
|
||||
str += 2;
|
||||
tmp -= 2;
|
||||
}
|
||||
|
||||
item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2);
|
||||
if (item->data == NULL) return NULL;
|
||||
item->len = tmp/2;
|
||||
|
||||
while (str[i]) {
|
||||
if ((str[i] >= '0') && (str[i] <= '9'))
|
||||
tmp = str[i] - '0';
|
||||
else if ((str[i] >= 'a') && (str[i] <= 'f'))
|
||||
tmp = str[i] - 'a' + 10;
|
||||
else if ((str[i] >= 'A') && (str[i] <= 'F'))
|
||||
tmp = str[i] - 'A' + 10;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
byteval = byteval * 16 + tmp;
|
||||
if ((i % 2) != 0) {
|
||||
item->data[i/2] = byteval;
|
||||
byteval = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* Copy all of the fields from srcParams into dstParams
|
||||
*/
|
||||
SECStatus
|
||||
EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
dstParams->arena = arena;
|
||||
dstParams->type = srcParams->type;
|
||||
dstParams->fieldID.size = srcParams->fieldID.size;
|
||||
dstParams->fieldID.type = srcParams->fieldID.type;
|
||||
if (srcParams->fieldID.type == ec_field_GFp) {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
|
||||
&srcParams->fieldID.u.prime));
|
||||
} else {
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
|
||||
&srcParams->fieldID.u.poly));
|
||||
}
|
||||
dstParams->fieldID.k1 = srcParams->fieldID.k1;
|
||||
dstParams->fieldID.k2 = srcParams->fieldID.k2;
|
||||
dstParams->fieldID.k3 = srcParams->fieldID.k3;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
|
||||
&srcParams->curve.a));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
|
||||
&srcParams->curve.b));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
|
||||
&srcParams->curve.seed));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
|
||||
&srcParams->base));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
|
||||
&srcParams->order));
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
|
||||
&srcParams->DEREncoding));
|
||||
dstParams->name = srcParams->name;
|
||||
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
|
||||
&srcParams->curveOID));
|
||||
dstParams->cofactor = srcParams->cofactor;
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
cleanup:
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
const ECCurveParams *curveParams;
|
||||
/* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
|
||||
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
|
||||
|
||||
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) goto cleanup;
|
||||
params->name = name;
|
||||
curveParams = ecCurve_map[params->name];
|
||||
CHECK_OK(curveParams);
|
||||
params->fieldID.size = curveParams->size;
|
||||
params->fieldID.type = field_type;
|
||||
if (field_type == ec_field_GFp) {
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime,
|
||||
curveParams->irr));
|
||||
} else {
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly,
|
||||
curveParams->irr));
|
||||
}
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a,
|
||||
curveParams->curvea));
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b,
|
||||
curveParams->curveb));
|
||||
genenc[0] = '0';
|
||||
genenc[1] = '4';
|
||||
genenc[2] = '\0';
|
||||
strcat(genenc, curveParams->genx);
|
||||
strcat(genenc, curveParams->geny);
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, genenc));
|
||||
CHECK_OK(hexString2SECItem(params->arena, ¶ms->order,
|
||||
curveParams->order));
|
||||
params->cofactor = curveParams->cofactor;
|
||||
|
||||
rv = SECSuccess;
|
||||
|
||||
cleanup:
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
SECOidTag tag;
|
||||
SECItem oid = { siBuffer, NULL, 0};
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("Encoded params in EC_DecodeParams: ");
|
||||
for (i = 0; i < encodedParams->len; i++) {
|
||||
printf("%02x:", encodedParams->data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
|
||||
(encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
};
|
||||
|
||||
oid.len = encodedParams->len - 2;
|
||||
oid.data = encodedParams->data + 2;
|
||||
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
|
||||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
params->arena = arena;
|
||||
params->cofactor = 0;
|
||||
params->type = ec_params_named;
|
||||
params->name = ECCurve_noName;
|
||||
|
||||
/* For named curves, fill out curveOID */
|
||||
params->curveOID.len = oid.len;
|
||||
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
|
||||
if (params->curveOID.data == NULL) goto cleanup;
|
||||
memcpy(params->curveOID.data, oid.data, oid.len);
|
||||
|
||||
#if EC_DEBUG
|
||||
printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
|
||||
#endif
|
||||
|
||||
switch (tag) {
|
||||
|
||||
/* Binary curves */
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB163V1:
|
||||
/* Populate params for c2pnb163v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB163V2:
|
||||
/* Populate params for c2pnb163v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB163V3:
|
||||
/* Populate params for c2pnb163v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB176V1:
|
||||
/* Populate params for c2pnb176v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB191V1:
|
||||
/* Populate params for c2tnb191v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB191V2:
|
||||
/* Populate params for c2tnb191v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB191V3:
|
||||
/* Populate params for c2tnb191v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB208W1:
|
||||
/* Populate params for c2pnb208w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB239V1:
|
||||
/* Populate params for c2tnb239v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB239V2:
|
||||
/* Populate params for c2tnb239v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB239V3:
|
||||
/* Populate params for c2tnb239v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB272W1:
|
||||
/* Populate params for c2pnb272w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB304W1:
|
||||
/* Populate params for c2pnb304w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB359V1:
|
||||
/* Populate params for c2tnb359v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2PNB368W1:
|
||||
/* Populate params for c2pnb368w1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_C2TNB431R1:
|
||||
/* Populate params for c2tnb431r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT113R1:
|
||||
/* Populate params for sect113r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT113R2:
|
||||
/* Populate params for sect113r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT131R1:
|
||||
/* Populate params for sect131r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT131R2:
|
||||
/* Populate params for sect131r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT163K1:
|
||||
/* Populate params for sect163k1
|
||||
* (the NIST K-163 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT163R1:
|
||||
/* Populate params for sect163r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT163R2:
|
||||
/* Populate params for sect163r2
|
||||
* (the NIST B-163 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT193R1:
|
||||
/* Populate params for sect193r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT193R2:
|
||||
/* Populate params for sect193r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT233K1:
|
||||
/* Populate params for sect233k1
|
||||
* (the NIST K-233 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT233R1:
|
||||
/* Populate params for sect233r1
|
||||
* (the NIST B-233 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT239K1:
|
||||
/* Populate params for sect239k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT283K1:
|
||||
/* Populate params for sect283k1
|
||||
* (the NIST K-283 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT283R1:
|
||||
/* Populate params for sect283r1
|
||||
* (the NIST B-283 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT409K1:
|
||||
/* Populate params for sect409k1
|
||||
* (the NIST K-409 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT409R1:
|
||||
/* Populate params for sect409r1
|
||||
* (the NIST B-409 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT571K1:
|
||||
/* Populate params for sect571k1
|
||||
* (the NIST K-571 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECT571R1:
|
||||
/* Populate params for sect571r1
|
||||
* (the NIST B-571 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
|
||||
params) );
|
||||
break;
|
||||
|
||||
/* Prime curves */
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME192V1:
|
||||
/* Populate params for prime192v1 aka secp192r1
|
||||
* (the NIST P-192 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME192V2:
|
||||
/* Populate params for prime192v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME192V3:
|
||||
/* Populate params for prime192v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME239V1:
|
||||
/* Populate params for prime239v1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME239V2:
|
||||
/* Populate params for prime239v2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME239V3:
|
||||
/* Populate params for prime239v3 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_ANSIX962_EC_PRIME256V1:
|
||||
/* Populate params for prime256v1 aka secp256r1
|
||||
* (the NIST P-256 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP112R1:
|
||||
/* Populate params for secp112r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP112R2:
|
||||
/* Populate params for secp112r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP128R1:
|
||||
/* Populate params for secp128r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP128R2:
|
||||
/* Populate params for secp128r2 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP160K1:
|
||||
/* Populate params for secp160k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP160R1:
|
||||
/* Populate params for secp160r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP160R2:
|
||||
/* Populate params for secp160r1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP192K1:
|
||||
/* Populate params for secp192k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP224K1:
|
||||
/* Populate params for secp224k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP224R1:
|
||||
/* Populate params for secp224r1
|
||||
* (the NIST P-224 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP256K1:
|
||||
/* Populate params for secp256k1 */
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP384R1:
|
||||
/* Populate params for secp384r1
|
||||
* (the NIST P-384 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
case SEC_OID_SECG_EC_SECP521R1:
|
||||
/* Populate params for secp521r1
|
||||
* (the NIST P-521 curve)
|
||||
*/
|
||||
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
|
||||
params) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
cleanup:
|
||||
if (!params->cofactor) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
#if EC_DEBUG
|
||||
printf("Unrecognized curve, returning NULL params\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
ECParams *params;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
/* Initialize an arena for the ECParams structure */
|
||||
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
|
||||
return SECFailure;
|
||||
|
||||
params = (ECParams *)PORT_ArenaZAlloc(arena, sizeof(ECParams));
|
||||
if (!params) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Copy the encoded params */
|
||||
SECITEM_AllocItem(arena, &(params->DEREncoding),
|
||||
encodedParams->len);
|
||||
memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
|
||||
|
||||
/* Fill out the rest of the ECParams structure based on
|
||||
* the encoded params
|
||||
*/
|
||||
rv = EC_FillParams(arena, encodedParams, params);
|
||||
if (rv == SECFailure) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
} else {
|
||||
*ecparams = params;;
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
@@ -1,351 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Network Security Services (NSS).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Red Hat, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* This file implements audit logging required by FIPS 140-2 Security
|
||||
* Level 2.
|
||||
*/
|
||||
|
||||
#include "prprf.h"
|
||||
#include "softoken.h"
|
||||
|
||||
/*
|
||||
* Print the value of the returned object handle in the output buffer
|
||||
* on a successful return of the PKCS #11 function. If the PKCS #11
|
||||
* function failed or the pointer to object handle is NULL (which is
|
||||
* the case for C_DeriveKey with CKM_TLS_KEY_AND_MAC_DERIVE), an empty
|
||||
* string is stored in the output buffer.
|
||||
*
|
||||
* out: the output buffer
|
||||
* outlen: the length of the output buffer
|
||||
* argName: the name of the "pointer to object handle" argument
|
||||
* phObject: the pointer to object handle
|
||||
* rv: the return value of the PKCS #11 function
|
||||
*/
|
||||
static void sftk_PrintReturnedObjectHandle(char *out, PRUint32 outlen,
|
||||
const char *argName, CK_OBJECT_HANDLE_PTR phObject, CK_RV rv)
|
||||
{
|
||||
if ((rv == CKR_OK) && phObject) {
|
||||
PR_snprintf(out, outlen,
|
||||
" *%s=0x%08lX", argName, (PRUint32)*phObject);
|
||||
} else {
|
||||
PORT_Assert(outlen != 0);
|
||||
out[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MECHANISM_BUFSIZE needs to be large enough for sftk_PrintMechanism,
|
||||
* which uses <= 49 bytes.
|
||||
*/
|
||||
#define MECHANISM_BUFSIZE 64
|
||||
|
||||
static void sftk_PrintMechanism(char *out, PRUint32 outlen,
|
||||
CK_MECHANISM_PTR pMechanism)
|
||||
{
|
||||
if (pMechanism) {
|
||||
/*
|
||||
* If we change the format string, we need to make sure
|
||||
* MECHANISM_BUFSIZE is still large enough. We allow
|
||||
* 20 bytes for %p on a 64-bit platform.
|
||||
*/
|
||||
PR_snprintf(out, outlen, "%p {mechanism=0x%08lX, ...}",
|
||||
pMechanism, (PRUint32)pMechanism->mechanism);
|
||||
} else {
|
||||
PR_snprintf(out, outlen, "%p", pMechanism);
|
||||
}
|
||||
}
|
||||
|
||||
void sftk_AuditCreateObject(CK_SESSION_HANDLE hSession,
|
||||
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_OBJECT_HANDLE_PTR phObject, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char shObject[32];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintReturnedObjectHandle(shObject, sizeof shObject,
|
||||
"phObject", phObject, rv);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_CreateObject(hSession=0x%08lX, pTemplate=%p, ulCount=%lu, "
|
||||
"phObject=%p)=0x%08lX%s",
|
||||
(PRUint32)hSession, pTemplate, (PRUint32)ulCount,
|
||||
phObject, (PRUint32)rv, shObject);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditCopyObject(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_OBJECT_HANDLE_PTR phNewObject, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char shNewObject[32];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintReturnedObjectHandle(shNewObject, sizeof shNewObject,
|
||||
"phNewObject", phNewObject, rv);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_CopyObject(hSession=0x%08lX, hObject=0x%08lX, "
|
||||
"pTemplate=%p, ulCount=%lu, phNewObject=%p)=0x%08lX%s",
|
||||
(PRUint32)hSession, (PRUint32)hObject,
|
||||
pTemplate, (PRUint32)ulCount, phNewObject, (PRUint32)rv, shNewObject);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
/* WARNING: hObject has been destroyed and can only be printed. */
|
||||
void sftk_AuditDestroyObject(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hObject, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_DestroyObject(hSession=0x%08lX, hObject=0x%08lX)=0x%08lX",
|
||||
(PRUint32)hSession, (PRUint32)hObject, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditGetObjectSize(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_GetObjectSize(hSession=0x%08lX, hObject=0x%08lX, "
|
||||
"pulSize=%p)=0x%08lX",
|
||||
(PRUint32)hSession, (PRUint32)hObject,
|
||||
pulSize, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditGetAttributeValue(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
|
||||
CK_ULONG ulCount, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_GetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, "
|
||||
"pTemplate=%p, ulCount=%lu)=0x%08lX",
|
||||
(PRUint32)hSession, (PRUint32)hObject,
|
||||
pTemplate, (PRUint32)ulCount, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditSetAttributeValue(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
|
||||
CK_ULONG ulCount, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_SetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, "
|
||||
"pTemplate=%p, ulCount=%lu)=0x%08lX",
|
||||
(PRUint32)hSession, (PRUint32)hObject,
|
||||
pTemplate, (PRUint32)ulCount, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditCryptInit(const char *opName, CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_%sInit(hSession=0x%08lX, pMechanism=%s, "
|
||||
"hKey=0x%08lX)=0x%08lX",
|
||||
opName, (PRUint32)hSession, mech,
|
||||
(PRUint32)hKey, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditGenerateKey(CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
|
||||
CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
char shKey[32];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_GenerateKey(hSession=0x%08lX, pMechanism=%s, "
|
||||
"pTemplate=%p, ulCount=%lu, phKey=%p)=0x%08lX%s",
|
||||
(PRUint32)hSession, mech,
|
||||
pTemplate, (PRUint32)ulCount, phKey, (PRUint32)rv, shKey);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditGenerateKeyPair(CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
|
||||
CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
|
||||
CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
|
||||
CK_OBJECT_HANDLE_PTR phPrivateKey, CK_RV rv)
|
||||
{
|
||||
char msg[512];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
char shPublicKey[32];
|
||||
char shPrivateKey[32];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
sftk_PrintReturnedObjectHandle(shPublicKey, sizeof shPublicKey,
|
||||
"phPublicKey", phPublicKey, rv);
|
||||
sftk_PrintReturnedObjectHandle(shPrivateKey, sizeof shPrivateKey,
|
||||
"phPrivateKey", phPrivateKey, rv);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_GenerateKeyPair(hSession=0x%08lX, pMechanism=%s, "
|
||||
"pPublicKeyTemplate=%p, ulPublicKeyAttributeCount=%lu, "
|
||||
"pPrivateKeyTemplate=%p, ulPrivateKeyAttributeCount=%lu, "
|
||||
"phPublicKey=%p, phPrivateKey=%p)=0x%08lX%s%s",
|
||||
(PRUint32)hSession, mech,
|
||||
pPublicKeyTemplate, (PRUint32)ulPublicKeyAttributeCount,
|
||||
pPrivateKeyTemplate, (PRUint32)ulPrivateKeyAttributeCount,
|
||||
phPublicKey, phPrivateKey, (PRUint32)rv, shPublicKey, shPrivateKey);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditWrapKey(CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
|
||||
CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
|
||||
CK_ULONG_PTR pulWrappedKeyLen, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_WrapKey(hSession=0x%08lX, pMechanism=%s, hWrappingKey=0x%08lX, "
|
||||
"hKey=0x%08lX, pWrappedKey=%p, pulWrappedKeyLen=%p)=0x%08lX",
|
||||
(PRUint32)hSession, mech, (PRUint32)hWrappingKey,
|
||||
(PRUint32)hKey, pWrappedKey, pulWrappedKeyLen, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditUnwrapKey(CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
|
||||
CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
|
||||
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
|
||||
CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
char shKey[32];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_UnwrapKey(hSession=0x%08lX, pMechanism=%s, "
|
||||
"hUnwrappingKey=0x%08lX, pWrappedKey=%p, ulWrappedKeyLen=%lu, "
|
||||
"pTemplate=%p, ulAttributeCount=%lu, phKey=%p)=0x%08lX%s",
|
||||
(PRUint32)hSession, mech,
|
||||
(PRUint32)hUnwrappingKey, pWrappedKey, (PRUint32)ulWrappedKeyLen,
|
||||
pTemplate, (PRUint32)ulAttributeCount, phKey, (PRUint32)rv, shKey);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditDeriveKey(CK_SESSION_HANDLE hSession,
|
||||
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
|
||||
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
|
||||
CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
|
||||
{
|
||||
char msg[512];
|
||||
char mech[MECHANISM_BUFSIZE];
|
||||
char shKey[32];
|
||||
char sTlsKeys[128];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
|
||||
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
|
||||
if ((rv == CKR_OK) &&
|
||||
(pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE)) {
|
||||
CK_SSL3_KEY_MAT_PARAMS *param =
|
||||
(CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
|
||||
CK_SSL3_KEY_MAT_OUT *keymat = param->pReturnedKeyMaterial;
|
||||
PR_snprintf(sTlsKeys, sizeof sTlsKeys,
|
||||
" hClientMacSecret=0x%08lX hServerMacSecret=0x%08lX"
|
||||
" hClientKey=0x%08lX hServerKey=0x%08lX",
|
||||
(PRUint32)keymat->hClientMacSecret,
|
||||
(PRUint32)keymat->hServerMacSecret,
|
||||
(PRUint32)keymat->hClientKey,
|
||||
(PRUint32)keymat->hServerKey);
|
||||
} else {
|
||||
sTlsKeys[0] = '\0';
|
||||
}
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_DeriveKey(hSession=0x%08lX, pMechanism=%s, "
|
||||
"hBaseKey=0x%08lX, pTemplate=%p, ulAttributeCount=%lu, "
|
||||
"phKey=%p)=0x%08lX%s%s",
|
||||
(PRUint32)hSession, mech,
|
||||
(PRUint32)hBaseKey, pTemplate,(PRUint32)ulAttributeCount,
|
||||
phKey, (PRUint32)rv, shKey, sTlsKeys);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
|
||||
void sftk_AuditDigestKey(CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hKey, CK_RV rv)
|
||||
{
|
||||
char msg[256];
|
||||
NSSAuditSeverity severity = (rv == CKR_OK) ?
|
||||
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
|
||||
|
||||
PR_snprintf(msg, sizeof msg,
|
||||
"C_DigestKey(hSession=0x%08lX, hKey=0x%08lX)=0x%08lX",
|
||||
(PRUint32)hSession, (PRUint32)hKey, (PRUint32)rv);
|
||||
sftk_LogAuditMessage(severity, msg);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* cdbhdl.h - certificate database handle
|
||||
* private to the certdb module
|
||||
*
|
||||
* $Id: cdbhdl.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#ifndef _CDBHDL_H_
|
||||
#define _CDBHDL_H_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "mcom_db.h"
|
||||
#include "pcertt.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
/*
|
||||
* Handle structure for open certificate databases
|
||||
*/
|
||||
struct NSSLOWCERTCertDBHandleStr {
|
||||
DB *permCertDB;
|
||||
PZMonitor *dbMon;
|
||||
PRBool dbVerify;
|
||||
PRInt32 ref; /* reference count */
|
||||
};
|
||||
|
||||
#ifdef DBM_USING_NSPR
|
||||
#define NO_RDONLY PR_RDONLY
|
||||
#define NO_RDWR PR_RDWR
|
||||
#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)
|
||||
#else
|
||||
#define NO_RDONLY O_RDONLY
|
||||
#define NO_RDWR O_RDWR
|
||||
#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC)
|
||||
#endif
|
||||
|
||||
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
|
||||
const char *type, int flags);
|
||||
typedef int (*rdbstatusfunc)(void);
|
||||
|
||||
#define RDB_FAIL 1
|
||||
#define RDB_RETRY 2
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags, int *status);
|
||||
|
||||
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
|
||||
const void * appData);
|
||||
SECStatus db_Copy(DB *dest,DB *src);
|
||||
int db_InitComplete(DB *db);
|
||||
|
||||
#endif
|
||||
@@ -1,102 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../freebl
|
||||
ifdef MOZILLA_SECURITY_BUILD
|
||||
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
|
||||
CRYPTODIR=../crypto
|
||||
endif
|
||||
|
||||
EXTRA_LIBS += \
|
||||
$(CRYPTOLIB) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
# can't do this in manifest.mn because OS_TARGET isn't defined there.
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
|
||||
# don't want the 32 in the shared library name
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
|
||||
|
||||
RES = $(OBJDIR)/$(LIBRARY_NAME).res
|
||||
RESNAME = $(LIBRARY_NAME).rc
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
else # ! NS_USE_GCC
|
||||
|
||||
EXTRA_SHARED_LIBS += \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
|
||||
$(NULL)
|
||||
endif # NS_USE_GCC
|
||||
|
||||
else
|
||||
|
||||
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
|
||||
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
OS_LIBS += -lbsm
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DDBM_USING_NSPR
|
||||
endif
|
||||
|
||||
# indicates dependency on freebl static lib
|
||||
$(SHARED_LIBRARY): $(CRYPTOLIB)
|
||||
@@ -1,647 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Berkeley DB 1.85 Shim code to handle blobs.
|
||||
*
|
||||
* $Id: dbmshim.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#include "mcom_db.h"
|
||||
#include "secitem.h"
|
||||
#include "nssb64.h"
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "lgdb.h"
|
||||
|
||||
/*
|
||||
* Blob block:
|
||||
* Byte 0 CERTDB Version -+ -+
|
||||
* Byte 1 certDBEntryTypeBlob | BLOB_HEAD_LEN |
|
||||
* Byte 2 flags (always '0'); | |
|
||||
* Byte 3 reserved (always '0'); -+ |
|
||||
* Byte 4 LSB length | <--BLOB_LENGTH_START | BLOB_BUF_LEN
|
||||
* Byte 5 . | |
|
||||
* Byte 6 . | BLOB_LENGTH_LEN |
|
||||
* Byte 7 MSB length | |
|
||||
* Byte 8 blob_filename -+ -+ <-- BLOB_NAME_START |
|
||||
* Byte 9 . | BLOB_NAME_LEN |
|
||||
* . . | |
|
||||
* Byte 37 . -+ -+
|
||||
*/
|
||||
#define DBS_BLOCK_SIZE (16*1024) /* 16 k */
|
||||
#define DBS_MAX_ENTRY_SIZE (DBS_BLOCK_SIZE - (2048)) /* 14 k */
|
||||
#define DBS_CACHE_SIZE DBS_BLOCK_SIZE*8
|
||||
#define ROUNDDIV(x,y) (x+(y-1))/y
|
||||
#define BLOB_HEAD_LEN 4
|
||||
#define BLOB_LENGTH_START BLOB_HEAD_LEN
|
||||
#define BLOB_LENGTH_LEN 4
|
||||
#define BLOB_NAME_START BLOB_LENGTH_START+BLOB_LENGTH_LEN
|
||||
#define BLOB_NAME_LEN 1+ROUNDDIV(SHA1_LENGTH,3)*4+1
|
||||
#define BLOB_BUF_LEN BLOB_HEAD_LEN+BLOB_LENGTH_LEN+BLOB_NAME_LEN
|
||||
|
||||
/* a Shim data structure. This data structure has a db built into it. */
|
||||
typedef struct DBSStr DBS;
|
||||
|
||||
struct DBSStr {
|
||||
DB db;
|
||||
char *blobdir;
|
||||
int mode;
|
||||
PRBool readOnly;
|
||||
PRFileMap *dbs_mapfile;
|
||||
unsigned char *dbs_addr;
|
||||
PRUint32 dbs_len;
|
||||
char staticBlobArea[BLOB_BUF_LEN];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* return true if the Datablock contains a blobtype
|
||||
*/
|
||||
static PRBool
|
||||
dbs_IsBlob(DBT *blobData)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)blobData->data;
|
||||
if (blobData->size < BLOB_BUF_LEN) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return addr && ((certDBEntryType) addr[1] == certDBEntryTypeBlob);
|
||||
}
|
||||
|
||||
/*
|
||||
* extract the filename in the blob of the real data set.
|
||||
* This value is not malloced (does not need to be freed by the caller.
|
||||
*/
|
||||
static const char *
|
||||
dbs_getBlobFileName(DBT *blobData)
|
||||
{
|
||||
char *addr = (char *)blobData->data;
|
||||
|
||||
return &addr[BLOB_NAME_START];
|
||||
}
|
||||
|
||||
/*
|
||||
* extract the size of the actual blob from the blob record
|
||||
*/
|
||||
static PRUint32
|
||||
dbs_getBlobSize(DBT *blobData)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)blobData->data;
|
||||
|
||||
return (PRUint32)(addr[BLOB_LENGTH_START+3] << 24) |
|
||||
(addr[BLOB_LENGTH_START+2] << 16) |
|
||||
(addr[BLOB_LENGTH_START+1] << 8) |
|
||||
addr[BLOB_LENGTH_START];
|
||||
}
|
||||
|
||||
|
||||
/* We are using base64 data for the filename, but base64 data can include a
|
||||
* '/' which is interpreted as a path separator on many platforms. Replace it
|
||||
* with an inocuous '-'. We don't need to convert back because we never actual
|
||||
* decode the filename.
|
||||
*/
|
||||
|
||||
static void
|
||||
dbs_replaceSlash(char *cp, int len)
|
||||
{
|
||||
while (len--) {
|
||||
if (*cp == '/') *cp = '-';
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a blob record from a key, data and return it in blobData.
|
||||
* NOTE: The data element is static data (keeping with the dbm model).
|
||||
*/
|
||||
static void
|
||||
dbs_mkBlob(DBS *dbsp,const DBT *key, const DBT *data, DBT *blobData)
|
||||
{
|
||||
unsigned char sha1_data[SHA1_LENGTH];
|
||||
char *b = dbsp->staticBlobArea;
|
||||
PRUint32 length = data->size;
|
||||
SECItem sha1Item;
|
||||
|
||||
b[0] = CERT_DB_FILE_VERSION; /* certdb version number */
|
||||
b[1] = (char) certDBEntryTypeBlob; /* type */
|
||||
b[2] = 0; /* flags */
|
||||
b[3] = 0; /* reserved */
|
||||
b[BLOB_LENGTH_START] = length & 0xff;
|
||||
b[BLOB_LENGTH_START+1] = (length >> 8) & 0xff;
|
||||
b[BLOB_LENGTH_START+2] = (length >> 16) & 0xff;
|
||||
b[BLOB_LENGTH_START+3] = (length >> 24) & 0xff;
|
||||
sha1Item.data = sha1_data;
|
||||
sha1Item.len = SHA1_LENGTH;
|
||||
SHA1_HashBuf(sha1_data,key->data,key->size);
|
||||
b[BLOB_NAME_START]='b'; /* Make sure we start with a alpha */
|
||||
NSSBase64_EncodeItem(NULL,&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1,&sha1Item);
|
||||
b[BLOB_BUF_LEN-1] = 0;
|
||||
dbs_replaceSlash(&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1);
|
||||
blobData->data = b;
|
||||
blobData->size = BLOB_BUF_LEN;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* construct a path to the actual blob. The string returned must be
|
||||
* freed by the caller with PR_smprintf_free.
|
||||
*
|
||||
* Note: this file does lots of consistancy checks on the DBT. The
|
||||
* routines that call this depend on these checks, so they don't worry
|
||||
* about them (success of this routine implies a good blobdata record).
|
||||
*/
|
||||
static char *
|
||||
dbs_getBlobFilePath(char *blobdir,DBT *blobData)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (blobdir == NULL) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
if (!dbs_IsBlob(blobData)) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
name = dbs_getBlobFileName(blobData);
|
||||
if (!name || *name == 0) {
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
return NULL;
|
||||
}
|
||||
return PR_smprintf("%s" PATH_SEPARATOR "%s", blobdir, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a blob file pointed to by the blob record.
|
||||
*/
|
||||
static void
|
||||
dbs_removeBlob(DBS *dbsp, DBT *blobData)
|
||||
{
|
||||
char *file;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
PR_Delete(file);
|
||||
PR_smprintf_free(file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Directory modes are slightly different, the 'x' bit needs to be on to
|
||||
* access them. Copy all the read bits to 'x' bits
|
||||
*/
|
||||
static int
|
||||
dbs_DirMode(int mode)
|
||||
{
|
||||
int x_bits = (mode >> 2) & 0111;
|
||||
return mode | x_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* write a data blob to it's file. blobdData is the blob record that will be
|
||||
* stored in the database. data is the actual data to go out on disk.
|
||||
*/
|
||||
static int
|
||||
dbs_writeBlob(DBS *dbsp, int mode, DBT *blobData, const DBT *data)
|
||||
{
|
||||
char *file = NULL;
|
||||
PRFileDesc *filed;
|
||||
PRStatus status;
|
||||
int len;
|
||||
int error = 0;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
|
||||
if (!file) {
|
||||
goto loser;
|
||||
}
|
||||
if (PR_Access(dbsp->blobdir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
|
||||
status = PR_MkDir(dbsp->blobdir,dbs_DirMode(mode));
|
||||
if (status != PR_SUCCESS) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
filed = PR_OpenFile(file,PR_CREATE_FILE|PR_TRUNCATE|PR_WRONLY, mode);
|
||||
if (filed == NULL) {
|
||||
error = PR_GetError();
|
||||
goto loser;
|
||||
}
|
||||
len = PR_Write(filed,data->data,data->size);
|
||||
error = PR_GetError();
|
||||
PR_Close(filed);
|
||||
if (len < (int)data->size) {
|
||||
goto loser;
|
||||
}
|
||||
PR_smprintf_free(file);
|
||||
return 0;
|
||||
|
||||
loser:
|
||||
if (file) {
|
||||
PR_Delete(file);
|
||||
PR_smprintf_free(file);
|
||||
}
|
||||
/* don't let close or delete reset the error */
|
||||
PR_SetError(error,0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* we need to keep a address map in memory between calls to DBM.
|
||||
* remember what we have mapped can close it when we get another dbm
|
||||
* call.
|
||||
*
|
||||
* NOTE: Not all platforms support mapped files. This code is designed to
|
||||
* detect this at runtime. If map files aren't supported the OS will indicate
|
||||
* this by failing the PR_Memmap call. In this case we emulate mapped files
|
||||
* by just reading in the file into regular memory. We signal this state by
|
||||
* making dbs_mapfile NULL and dbs_addr non-NULL.
|
||||
*/
|
||||
|
||||
static void
|
||||
dbs_freemap(DBS *dbsp)
|
||||
{
|
||||
if (dbsp->dbs_mapfile) {
|
||||
PR_MemUnmap(dbsp->dbs_addr,dbsp->dbs_len);
|
||||
PR_CloseFileMap(dbsp->dbs_mapfile);
|
||||
dbsp->dbs_mapfile = NULL;
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
} else if (dbsp->dbs_addr) {
|
||||
PORT_Free(dbsp->dbs_addr);
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dbs_setmap(DBS *dbsp, PRFileMap *mapfile, unsigned char *addr, PRUint32 len)
|
||||
{
|
||||
dbsp->dbs_mapfile = mapfile;
|
||||
dbsp->dbs_addr = addr;
|
||||
dbsp->dbs_len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* platforms that cannot map the file need to read it into a temp buffer.
|
||||
*/
|
||||
static unsigned char *
|
||||
dbs_EmulateMap(PRFileDesc *filed, int len)
|
||||
{
|
||||
unsigned char *addr;
|
||||
PRInt32 dataRead;
|
||||
|
||||
addr = PORT_Alloc(len);
|
||||
if (addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dataRead = PR_Read(filed,addr,len);
|
||||
if (dataRead != len) {
|
||||
PORT_Free(addr);
|
||||
if (dataRead > 0) {
|
||||
/* PR_Read didn't set an error, we need to */
|
||||
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pull a database record off the disk
|
||||
* data points to the blob record on input and the real record (if we could
|
||||
* read it) on output. if there is an error data is not modified.
|
||||
*/
|
||||
static int
|
||||
dbs_readBlob(DBS *dbsp, DBT *data)
|
||||
{
|
||||
char *file = NULL;
|
||||
PRFileDesc *filed = NULL;
|
||||
PRFileMap *mapfile = NULL;
|
||||
unsigned char *addr = NULL;
|
||||
int error;
|
||||
int len = -1;
|
||||
|
||||
file = dbs_getBlobFilePath(dbsp->blobdir, data);
|
||||
if (!file) {
|
||||
goto loser;
|
||||
}
|
||||
filed = PR_OpenFile(file,PR_RDONLY,0);
|
||||
PR_smprintf_free(file); file = NULL;
|
||||
if (filed == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
len = dbs_getBlobSize(data);
|
||||
mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
|
||||
if (mapfile == NULL) {
|
||||
/* USE PR_GetError instead of PORT_GetError here
|
||||
* because we are getting the error from PR_xxx
|
||||
* function */
|
||||
if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
|
||||
goto loser;
|
||||
}
|
||||
addr = dbs_EmulateMap(filed, len);
|
||||
} else {
|
||||
addr = PR_MemMap(mapfile, 0, len);
|
||||
}
|
||||
if (addr == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
PR_Close(filed);
|
||||
dbs_setmap(dbsp,mapfile,addr,len);
|
||||
|
||||
data->data = addr;
|
||||
data->size = len;
|
||||
return 0;
|
||||
|
||||
loser:
|
||||
/* preserve the error code */
|
||||
error = PR_GetError();
|
||||
if (mapfile) {
|
||||
PR_CloseFileMap(mapfile);
|
||||
}
|
||||
if (filed) {
|
||||
PR_Close(filed);
|
||||
}
|
||||
PR_SetError(error,0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* actual DBM shims
|
||||
*/
|
||||
static int
|
||||
dbs_get(const DB *dbs, const DBT *key, DBT *data, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
ret = (* db->get)(db, key, data, flags);
|
||||
if ((ret == 0) && dbs_IsBlob(data)) {
|
||||
ret = dbs_readBlob(dbsp,data);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_put(const DB *dbs, DBT *key, const DBT *data, unsigned int flags)
|
||||
{
|
||||
DBT blob;
|
||||
int ret = 0;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
/* If the db is readonly, just pass the data down to rdb and let it fail */
|
||||
if (!dbsp->readOnly) {
|
||||
DBT oldData;
|
||||
int ret1;
|
||||
|
||||
/* make sure the current record is deleted if it's a blob */
|
||||
ret1 = (*db->get)(db,key,&oldData,0);
|
||||
if ((ret1 == 0) && flags == R_NOOVERWRITE) {
|
||||
/* let DBM return the error to maintain consistancy */
|
||||
return (* db->put)(db, key, data, flags);
|
||||
}
|
||||
if ((ret1 == 0) && dbs_IsBlob(&oldData)) {
|
||||
dbs_removeBlob(dbsp, &oldData);
|
||||
}
|
||||
|
||||
if (data->size > DBS_MAX_ENTRY_SIZE) {
|
||||
dbs_mkBlob(dbsp,key,data,&blob);
|
||||
ret = dbs_writeBlob(dbsp, dbsp->mode, &blob, data);
|
||||
data = &blob;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = (* db->put)(db, key, data, flags);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_sync(const DB *dbs, unsigned int flags)
|
||||
{
|
||||
DB *db = (DB *)dbs->internal;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
return (* db->sync)(db, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_del(const DB *dbs, const DBT *key, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
if (!dbsp->readOnly) {
|
||||
DBT oldData;
|
||||
ret = (*db->get)(db,key,&oldData,0);
|
||||
if ((ret == 0) && dbs_IsBlob(&oldData)) {
|
||||
dbs_removeBlob(dbsp,&oldData);
|
||||
}
|
||||
}
|
||||
|
||||
return (* db->del)(db, key, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_seq(const DB *dbs, DBT *key, DBT *data, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
|
||||
ret = (* db->seq)(db, key, data, flags);
|
||||
if ((ret == 0) && dbs_IsBlob(data)) {
|
||||
/* don't return a blob read as an error so traversals keep going */
|
||||
(void) dbs_readBlob(dbsp,data);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_close(DB *dbs)
|
||||
{
|
||||
DBS *dbsp = (DBS *)dbs;
|
||||
DB *db = (DB *)dbs->internal;
|
||||
int ret;
|
||||
|
||||
dbs_freemap(dbsp);
|
||||
ret = (* db->close)(db);
|
||||
PORT_Free(dbsp->blobdir);
|
||||
PORT_Free(dbsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dbs_fd(const DB *dbs)
|
||||
{
|
||||
DB *db = (DB *)dbs->internal;
|
||||
|
||||
return (* db->fd)(db);
|
||||
}
|
||||
|
||||
/*
|
||||
* the naming convention we use is
|
||||
* change the .xxx into .dir. (for nss it's always .db);
|
||||
* if no .extension exists or is equal to .dir, add a .dir
|
||||
* the returned data must be freed.
|
||||
*/
|
||||
#define DIRSUFFIX ".dir"
|
||||
static char *
|
||||
dbs_mkBlobDirName(const char *dbname)
|
||||
{
|
||||
int dbname_len = PORT_Strlen(dbname);
|
||||
int dbname_end = dbname_len;
|
||||
const char *cp;
|
||||
char *blobDir = NULL;
|
||||
|
||||
/* scan back from the end looking for either a directory separator, a '.',
|
||||
* or the end of the string. NOTE: Windows should check for both separators
|
||||
* here. For now this is safe because we know NSS always uses a '.'
|
||||
*/
|
||||
for (cp = &dbname[dbname_len];
|
||||
(cp > dbname) && (*cp != '.') && (*cp != *PATH_SEPARATOR) ;
|
||||
cp--)
|
||||
/* Empty */ ;
|
||||
if (*cp == '.') {
|
||||
dbname_end = cp - dbname;
|
||||
if (PORT_Strcmp(cp,DIRSUFFIX) == 0) {
|
||||
dbname_end = dbname_len;
|
||||
}
|
||||
}
|
||||
blobDir = PORT_ZAlloc(dbname_end+sizeof(DIRSUFFIX));
|
||||
if (blobDir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PORT_Memcpy(blobDir,dbname,dbname_end);
|
||||
PORT_Memcpy(&blobDir[dbname_end],DIRSUFFIX,sizeof(DIRSUFFIX));
|
||||
return blobDir;
|
||||
}
|
||||
|
||||
#define DBM_DEFAULT 0
|
||||
static const HASHINFO dbs_hashInfo = {
|
||||
DBS_BLOCK_SIZE, /* bucket size, must be greater than = to
|
||||
* or maximum entry size (+ header)
|
||||
* we allow before blobing */
|
||||
DBM_DEFAULT, /* Fill Factor */
|
||||
DBM_DEFAULT, /* number of elements */
|
||||
DBS_CACHE_SIZE, /* cache size */
|
||||
DBM_DEFAULT, /* hash function */
|
||||
DBM_DEFAULT, /* byte order */
|
||||
};
|
||||
|
||||
/*
|
||||
* the open function. NOTE: this is the only exposed function in this file.
|
||||
* everything else is called through the function table pointer.
|
||||
*/
|
||||
DB *
|
||||
dbsopen(const char *dbname, int flags, int mode, DBTYPE type,
|
||||
const void *userData)
|
||||
{
|
||||
DB *db = NULL,*dbs = NULL;
|
||||
DBS *dbsp = NULL;
|
||||
|
||||
/* NOTE: we are overriding userData with dbs_hashInfo. since all known
|
||||
* callers pass 0, this is ok, otherwise we should merge the two */
|
||||
|
||||
dbsp = (DBS *)PORT_ZAlloc(sizeof(DBS));
|
||||
if (!dbsp) {
|
||||
return NULL;
|
||||
}
|
||||
dbs = &dbsp->db;
|
||||
|
||||
dbsp->blobdir=dbs_mkBlobDirName(dbname);
|
||||
if (dbsp->blobdir == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
dbsp->mode = mode;
|
||||
dbsp->readOnly = (PRBool)(flags == NO_RDONLY);
|
||||
dbsp->dbs_mapfile = NULL;
|
||||
dbsp->dbs_addr = NULL;
|
||||
dbsp->dbs_len = 0;
|
||||
|
||||
/* the real dbm call */
|
||||
db = dbopen(dbname, flags, mode, type, &dbs_hashInfo);
|
||||
if (db == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
dbs->internal = (void *) db;
|
||||
dbs->type = type;
|
||||
dbs->close = dbs_close;
|
||||
dbs->get = dbs_get;
|
||||
dbs->del = dbs_del;
|
||||
dbs->put = dbs_put;
|
||||
dbs->seq = dbs_seq;
|
||||
dbs->sync = dbs_sync;
|
||||
dbs->fd = dbs_fd;
|
||||
|
||||
return dbs;
|
||||
loser:
|
||||
if (db) {
|
||||
(*db->close)(db);
|
||||
}
|
||||
if (dbsp) {
|
||||
if (dbsp->blobdir) {
|
||||
PORT_Free(dbsp->blobdir);
|
||||
}
|
||||
PORT_Free(dbsp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* private.h - Private data structures for the software token library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: keydbi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _KEYDBI_H_
|
||||
#define _KEYDBI_H_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "seccomon.h"
|
||||
#include "mcom_db.h"
|
||||
|
||||
/*
|
||||
* Handle structure for open key databases
|
||||
*/
|
||||
struct NSSLOWKEYDBHandleStr {
|
||||
DB *db;
|
||||
DB *updatedb; /* used when updating an old version */
|
||||
SECItem *global_salt; /* password hashing salt for this db */
|
||||
int version; /* version of the database */
|
||||
char *appname; /* multiaccess app name */
|
||||
char *dbname; /* name of the openned DB */
|
||||
PRBool readOnly; /* is the DB read only */
|
||||
PRLock *lock;
|
||||
PRInt32 ref; /* reference count */
|
||||
};
|
||||
|
||||
/*
|
||||
** Typedef for callback for traversing key database.
|
||||
** "key" is the key used to index the data in the database (nickname)
|
||||
** "data" is the key data
|
||||
** "pdata" is the user's data
|
||||
*/
|
||||
typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
|
||||
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
** Traverse the entire key database, and pass the nicknames and keys to a
|
||||
** user supplied function.
|
||||
** "f" is the user function to call for each key
|
||||
** "udata" is the user's data, which is passed through to "f"
|
||||
*/
|
||||
extern SECStatus nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYTraverseKeysFunc f,
|
||||
void *udata);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _KEYDBI_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,955 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "secitem.h"
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "pcert.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "blapi.h"
|
||||
#include "secder.h"
|
||||
|
||||
#include "keydbi.h"
|
||||
|
||||
/*
|
||||
* ******************** Object Creation Utilities ***************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Certificate Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
SECItem derCert;
|
||||
NSSLOWCERTCertificate *cert;
|
||||
NSSLOWCERTCertTrust *trust = NULL;
|
||||
NSSLOWCERTCertTrust userTrust =
|
||||
{ CERTDB_USER, CERTDB_USER, CERTDB_USER };
|
||||
NSSLOWCERTCertTrust defTrust =
|
||||
{ CERTDB_TRUSTED_UNKNOWN,
|
||||
CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
|
||||
char *label = NULL;
|
||||
char *email = NULL;
|
||||
SECStatus rv;
|
||||
PRBool inDB = PR_TRUE;
|
||||
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
CK_CERTIFICATE_TYPE type;
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/* We only support X.509 Certs for now */
|
||||
attribute = lg_FindAttribute(CKA_CERTIFICATE_TYPE, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
type = *(CK_CERTIFICATE_TYPE *)attribute->pValue;
|
||||
|
||||
if (type != CKC_X_509) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/* X.509 Certificate */
|
||||
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* get the der cert */
|
||||
attribute = lg_FindAttribute(CKA_VALUE, templ, count);
|
||||
if (!attribute) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
derCert.type = 0;
|
||||
derCert.data = (unsigned char *)attribute->pValue;
|
||||
derCert.len = attribute->ulValueLen ;
|
||||
|
||||
label = lg_getString(CKA_LABEL, templ, count);
|
||||
|
||||
cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
|
||||
if (cert == NULL) {
|
||||
cert = nsslowcert_DecodeDERCertificate(&derCert, label);
|
||||
inDB = PR_FALSE;
|
||||
}
|
||||
if (cert == NULL) {
|
||||
if (label) PORT_Free(label);
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle) {
|
||||
if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
|
||||
trust = &userTrust;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inDB) {
|
||||
if (!trust) trust = &defTrust;
|
||||
rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
|
||||
} else {
|
||||
rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
|
||||
SECSuccess;
|
||||
}
|
||||
|
||||
if (label) PORT_Free(label);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a NULL S/MIME profile if necessary.
|
||||
*/
|
||||
email = lg_getString(CKA_NETSCAPE_EMAIL, templ, count);
|
||||
if (email) {
|
||||
certDBEntrySMime *entry;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
|
||||
if (!entry) {
|
||||
nsslowcert_SaveSMimeProfile(certHandle, email,
|
||||
&cert->derSubject, NULL, NULL);
|
||||
} else {
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(email);
|
||||
}
|
||||
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
|
||||
{
|
||||
unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
|
||||
CERTDB_TRUSTED_CA;
|
||||
switch (trust) {
|
||||
case CKT_NETSCAPE_TRUSTED:
|
||||
return CERTDB_VALID_PEER|CERTDB_TRUSTED;
|
||||
case CKT_NETSCAPE_TRUSTED_DELEGATOR:
|
||||
return CERTDB_VALID_CA|trustCA;
|
||||
case CKT_NETSCAPE_UNTRUSTED:
|
||||
return CERTDB_NOT_TRUSTED;
|
||||
case CKT_NETSCAPE_MUST_VERIFY:
|
||||
return 0;
|
||||
case CKT_NETSCAPE_VALID: /* implies must verify */
|
||||
return CERTDB_VALID_PEER;
|
||||
case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */
|
||||
return CERTDB_VALID_CA;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CERTDB_TRUSTED_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *issuer = NULL;
|
||||
const CK_ATTRIBUTE *serial = NULL;
|
||||
NSSLOWCERTCertificate *cert = NULL;
|
||||
const CK_ATTRIBUTE *trust;
|
||||
CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
|
||||
CK_BBOOL stepUp;
|
||||
NSSLOWCERTCertTrust dbTrust = { 0 };
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
|
||||
NSSLOWCERTIssuerAndSN issuerSN;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
issuer = lg_FindAttribute(CKA_ISSUER, templ, count);
|
||||
serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count);
|
||||
|
||||
if (issuer && serial) {
|
||||
issuerSN.derIssuer.data = (unsigned char *)issuer->pValue;
|
||||
issuerSN.derIssuer.len = issuer->ulValueLen ;
|
||||
|
||||
issuerSN.serialNumber.data = (unsigned char *)serial->pValue;
|
||||
issuerSN.serialNumber.len = serial->ulValueLen ;
|
||||
|
||||
cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
|
||||
}
|
||||
|
||||
if (cert == NULL) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust);
|
||||
lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust);
|
||||
stepUp = CK_FALSE;
|
||||
trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
|
||||
if (trust) {
|
||||
if (trust->ulValueLen == sizeof(CK_BBOOL)) {
|
||||
stepUp = *(CK_BBOOL*)trust->pValue;
|
||||
}
|
||||
}
|
||||
|
||||
/* preserve certain old fields */
|
||||
if (cert->trust) {
|
||||
dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
dbTrust.emailFlags=
|
||||
cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
dbTrust.objectSigningFlags =
|
||||
cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
|
||||
}
|
||||
|
||||
dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE);
|
||||
dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE);
|
||||
dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE);
|
||||
dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE);
|
||||
if (stepUp) {
|
||||
dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
|
||||
}
|
||||
|
||||
rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
|
||||
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST);
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
SECItem derSubj,rawProfile,rawTime,emailKey;
|
||||
SECItem *pRawProfile = NULL;
|
||||
SECItem *pRawTime = NULL;
|
||||
char *email = NULL;
|
||||
const CK_ATTRIBUTE *subject = NULL,
|
||||
*profile = NULL,
|
||||
*time = NULL;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
CK_RV ck_rv = CKR_OK;
|
||||
|
||||
/* we can't store any certs private */
|
||||
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* lookup SUBJECT */
|
||||
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
|
||||
PORT_Assert(subject);
|
||||
if (!subject) {
|
||||
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
derSubj.data = (unsigned char *)subject->pValue;
|
||||
derSubj.len = subject->ulValueLen ;
|
||||
derSubj.type = 0;
|
||||
|
||||
/* lookup VALUE */
|
||||
profile = lg_FindAttribute(CKA_VALUE,templ,count);
|
||||
if (profile) {
|
||||
rawProfile.data = (unsigned char *)profile->pValue;
|
||||
rawProfile.len = profile->ulValueLen ;
|
||||
rawProfile.type = siBuffer;
|
||||
pRawProfile = &rawProfile;
|
||||
}
|
||||
|
||||
/* lookup Time */
|
||||
time = lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP,templ,count);
|
||||
if (time) {
|
||||
rawTime.data = (unsigned char *)time->pValue;
|
||||
rawTime.len = time->ulValueLen ;
|
||||
rawTime.type = siBuffer;
|
||||
pRawTime = &rawTime;
|
||||
}
|
||||
|
||||
|
||||
email = lg_getString(CKA_NETSCAPE_EMAIL,templ,count);
|
||||
if (!email) {
|
||||
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Store S/MIME Profile by SUBJECT */
|
||||
rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
|
||||
pRawProfile,pRawTime);
|
||||
if (rv != SECSuccess) {
|
||||
ck_rv = CKR_DEVICE_ERROR;
|
||||
goto loser;
|
||||
}
|
||||
emailKey.data = (unsigned char *)email;
|
||||
emailKey.len = PORT_Strlen(email)+1;
|
||||
|
||||
*handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
|
||||
|
||||
loser:
|
||||
if (email) PORT_Free(email);
|
||||
|
||||
return ck_rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Trust Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
PRBool isKRL = PR_FALSE;
|
||||
SECItem derSubj,derCrl;
|
||||
char *url = NULL;
|
||||
const CK_ATTRIBUTE *subject,*crl;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
|
||||
/* we can't store any private crls */
|
||||
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (certHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
/* lookup SUBJECT */
|
||||
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
|
||||
if (!subject) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
derSubj.data = (unsigned char *)subject->pValue;
|
||||
derSubj.len = subject->ulValueLen ;
|
||||
|
||||
/* lookup VALUE */
|
||||
crl = lg_FindAttribute(CKA_VALUE,templ,count);
|
||||
PORT_Assert(crl);
|
||||
if (!crl) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
derCrl.data = (unsigned char *)crl->pValue;
|
||||
derCrl.len = crl->ulValueLen ;
|
||||
|
||||
url = lg_getString(CKA_NETSCAPE_URL,templ,count);
|
||||
isKRL = lg_isTrue(CKA_NETSCAPE_KRL,templ,count);
|
||||
|
||||
/* Store CRL by SUBJECT */
|
||||
rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
|
||||
|
||||
if (url) {
|
||||
PORT_Free(url);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* if we overwrote the existing CRL, poison the handle entry so we get
|
||||
* a new object handle */
|
||||
(void) lg_poisonHandle(sdb, &derSubj,
|
||||
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
|
||||
*handle = lg_mkHandle(sdb, &derSubj,
|
||||
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Public Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
|
||||
CK_RV crv;
|
||||
NSSLOWKEYPrivateKey *priv;
|
||||
SECItem pubKey;
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
|
||||
switch (key_type) {
|
||||
case CKK_RSA:
|
||||
pubKeyAttr = CKA_MODULUS;
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case CKK_EC:
|
||||
pubKeyAttr = CKA_EC_POINT;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
case CKK_DSA:
|
||||
case CKK_DH:
|
||||
break;
|
||||
default:
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
|
||||
crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,&pubKey);
|
||||
if (crv != CKR_OK) return crv;
|
||||
|
||||
PORT_Assert(pubKey.data);
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle == NULL) {
|
||||
PORT_Free(pubKey.data);
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
if (keyHandle->version != 3) {
|
||||
unsigned char buf[SHA1_LENGTH];
|
||||
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
|
||||
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
|
||||
pubKey.len = sizeof(buf);
|
||||
}
|
||||
/* make sure the associated private key already exists */
|
||||
/* only works if we are logged in */
|
||||
priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, sdb /*password*/);
|
||||
if (priv == NULL) {
|
||||
PORT_Free(pubKey.data);
|
||||
return crv;
|
||||
}
|
||||
nsslowkey_DestroyPrivateKey(priv);
|
||||
|
||||
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PUB);
|
||||
PORT_Free(pubKey.data);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* make a private key from a verified object */
|
||||
static NSSLOWKEYPrivateKey *
|
||||
lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
CK_KEY_TYPE key_type, CK_RV *crvp)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
PLArenaPool *arena;
|
||||
CK_RV crv = CKR_OK;
|
||||
SECStatus rv;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
*crvp = CKR_HOST_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
privKey = (NSSLOWKEYPrivateKey *)
|
||||
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
|
||||
if (privKey == NULL) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
*crvp = CKR_HOST_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* in future this would be a switch on key_type */
|
||||
privKey->arena = arena;
|
||||
switch (key_type) {
|
||||
case CKK_RSA:
|
||||
privKey->keyType = NSSLOWKEYRSAKey;
|
||||
crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count,
|
||||
&privKey->u.rsa.modulus);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count,
|
||||
&privKey->u.rsa.publicExponent);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count,
|
||||
&privKey->u.rsa.privateExponent, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count,
|
||||
&privKey->u.rsa.prime1, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count,
|
||||
&privKey->u.rsa.prime2, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count,
|
||||
&privKey->u.rsa.exponent1, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count,
|
||||
&privKey->u.rsa.exponent2, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count,
|
||||
&privKey->u.rsa.coefficient, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
|
||||
NSSLOWKEY_VERSION);
|
||||
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
|
||||
case CKK_DSA:
|
||||
privKey->keyType = NSSLOWKEYDSAKey;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
|
||||
&privKey->u.dsa.params.prime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count,
|
||||
&privKey->u.dsa.params.subPrime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
|
||||
&privKey->u.dsa.params.base);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.dsa.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ,count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.dsa.publicValue);
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
break;
|
||||
|
||||
case CKK_DH:
|
||||
privKey->keyType = NSSLOWKEYDHKey;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
|
||||
&privKey->u.dh.prime);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
|
||||
&privKey->u.dh.base);
|
||||
if (crv != CKR_OK) break;
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.dh.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.dh.publicValue);
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case CKK_EC:
|
||||
privKey->keyType = NSSLOWKEYECKey;
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count,
|
||||
&privKey->u.ec.ecParams.DEREncoding);
|
||||
if (crv != CKR_OK) break;
|
||||
|
||||
/* Fill out the rest of the ecParams structure
|
||||
* based on the encoded params
|
||||
*/
|
||||
if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
|
||||
&privKey->u.ec.ecParams) != SECSuccess) {
|
||||
crv = CKR_DOMAIN_PARAMS_INVALID;
|
||||
break;
|
||||
}
|
||||
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
|
||||
&privKey->u.ec.privateValue, sdb);
|
||||
if (crv != CKR_OK) break;
|
||||
if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) {
|
||||
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
|
||||
&privKey->u.ec.publicValue);
|
||||
if (crv != CKR_OK) break;
|
||||
/* privKey was zero'd so public value is already set to NULL, 0
|
||||
* if we don't set it explicitly */
|
||||
}
|
||||
rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
|
||||
NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
|
||||
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
default:
|
||||
crv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
*crvp = crv;
|
||||
if (crv != CKR_OK) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
return privKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Private Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
char *label;
|
||||
SECStatus rv = SECSuccess;
|
||||
CK_RV crv = CKR_DEVICE_ERROR;
|
||||
SECItem pubKey;
|
||||
NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb);
|
||||
|
||||
if (keyHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv);
|
||||
if (privKey == NULL) return crv;
|
||||
label = lg_getString(CKA_LABEL,templ,count);
|
||||
|
||||
crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey);
|
||||
if (crv != CKR_OK) {
|
||||
crv = CKR_TEMPLATE_INCOMPLETE;
|
||||
rv = SECFailure;
|
||||
goto fail;
|
||||
}
|
||||
#ifdef notdef
|
||||
if (keyHandle->version != 3) {
|
||||
unsigned char buf[SHA1_LENGTH];
|
||||
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
|
||||
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
|
||||
pubKey.len = sizeof(buf);
|
||||
}
|
||||
#endif
|
||||
/* get the key type */
|
||||
if (key_type == CKK_RSA) {
|
||||
rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
|
||||
if (rv == SECFailure) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
|
||||
label, sdb /*->password*/);
|
||||
|
||||
fail:
|
||||
if (label) PORT_Free(label);
|
||||
*handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV);
|
||||
if (pubKey.data) PORT_Free(pubKey.data);
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
if (rv != SECSuccess) return crv;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
#define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
|
||||
#define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
|
||||
/*
|
||||
* Secret keys must have a CKA_ID value to be stored in the database. This code
|
||||
* will generate one if there wasn't one already.
|
||||
*/
|
||||
static CK_RV
|
||||
lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
|
||||
{
|
||||
unsigned int retries;
|
||||
SECStatus rv = SECSuccess;
|
||||
CK_RV crv = CKR_OK;
|
||||
|
||||
id->data = NULL;
|
||||
if (label) {
|
||||
id->data = (unsigned char *)PORT_Strdup(label);
|
||||
if (id->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
id->len = PORT_Strlen(label)+1;
|
||||
if (!nsslowkey_KeyForIDExists(handle,id)) {
|
||||
return CKR_OK;
|
||||
}
|
||||
PORT_Free(id->data);
|
||||
id->data = NULL;
|
||||
id->len = 0;
|
||||
}
|
||||
id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE);
|
||||
if (id->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
id->len = LG_KEY_ID_SIZE;
|
||||
|
||||
retries = 0;
|
||||
do {
|
||||
rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
|
||||
} while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
|
||||
(++retries <= LG_KEY_MAX_RETRIES));
|
||||
|
||||
if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) {
|
||||
crv = CKR_DEVICE_ERROR; /* random number generator is bad */
|
||||
PORT_Free(id->data);
|
||||
id->data = NULL;
|
||||
id->len = 0;
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count, CK_KEY_TYPE key_type,
|
||||
SECItem *pubkey, SDB *sdbpw)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *privKey = 0;
|
||||
PLArenaPool *arena = 0;
|
||||
CK_KEY_TYPE keyType;
|
||||
PRUint32 keyTypeStorage;
|
||||
SECItem keyTypeItem;
|
||||
CK_RV crv;
|
||||
SECStatus rv;
|
||||
static unsigned char derZero[1] = { 0 };
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
privKey = (NSSLOWKEYPrivateKey *)
|
||||
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
|
||||
if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
privKey->arena = arena;
|
||||
|
||||
/* Secret keys are represented in the database as "fake" RSA keys.
|
||||
* The RSA key is marked as a secret key representation by setting the
|
||||
* public exponent field to 0, which is an invalid RSA exponent.
|
||||
* The other fields are set as follows:
|
||||
* modulus - CKA_ID value for the secret key
|
||||
* private exponent - CKA_VALUE (the key itself)
|
||||
* coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
|
||||
* is used for the key.
|
||||
* all others - set to integer 0
|
||||
*/
|
||||
privKey->keyType = NSSLOWKEYRSAKey;
|
||||
|
||||
/* The modulus is set to the key id of the symmetric key */
|
||||
crv = lg_Attribute2SecItem(arena, CKA_ID, templ, count,
|
||||
&privKey->u.rsa.modulus);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* The public exponent is set to 0 length to indicate a special key */
|
||||
privKey->u.rsa.publicExponent.len = sizeof derZero;
|
||||
privKey->u.rsa.publicExponent.data = derZero;
|
||||
|
||||
/* The private exponent is the actual key value */
|
||||
crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count,
|
||||
&privKey->u.rsa.privateExponent, sdbpw);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* All other fields empty - needs testing */
|
||||
privKey->u.rsa.prime1.len = sizeof derZero;
|
||||
privKey->u.rsa.prime1.data = derZero;
|
||||
|
||||
privKey->u.rsa.prime2.len = sizeof derZero;
|
||||
privKey->u.rsa.prime2.data = derZero;
|
||||
|
||||
privKey->u.rsa.exponent1.len = sizeof derZero;
|
||||
privKey->u.rsa.exponent1.data = derZero;
|
||||
|
||||
privKey->u.rsa.exponent2.len = sizeof derZero;
|
||||
privKey->u.rsa.exponent2.data = derZero;
|
||||
|
||||
/* Coeficient set to KEY_TYPE */
|
||||
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
/* on 64 bit platforms, we still want to store 32 bits of keyType (This is
|
||||
* safe since the PKCS #11 defines for all types are 32 bits or less). */
|
||||
keyTypeStorage = (PRUint32) keyType;
|
||||
keyTypeStorage = PR_htonl(keyTypeStorage);
|
||||
keyTypeItem.data = (unsigned char *)&keyTypeStorage;
|
||||
keyTypeItem.len = sizeof (keyTypeStorage);
|
||||
rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Private key version field set normally for compatibility */
|
||||
rv = DER_SetUInteger(privKey->arena,
|
||||
&privKey->u.rsa.version, NSSLOWKEY_VERSION);
|
||||
if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
|
||||
|
||||
loser:
|
||||
if (crv != CKR_OK) {
|
||||
PORT_FreeArena(arena,PR_FALSE);
|
||||
privKey = 0;
|
||||
}
|
||||
|
||||
return privKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Secret Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
NSSLOWKEYPrivateKey *privKey = NULL;
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
SECItem pubKey;
|
||||
char *label = NULL;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
pubKey.data = 0;
|
||||
|
||||
/* If the object is a TOKEN object, store in the database */
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
|
||||
if (keyHandle == NULL) {
|
||||
return CKR_TOKEN_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
label = lg_getString(CKA_LABEL,templ,count);
|
||||
|
||||
crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey);
|
||||
/* Should this be ID? */
|
||||
if (crv != CKR_OK) goto loser;
|
||||
|
||||
/* if we don't have an ID, generate one */
|
||||
if (pubKey.len == 0) {
|
||||
if (pubKey.data) {
|
||||
PORT_Free(pubKey.data);
|
||||
pubKey.data = NULL;
|
||||
}
|
||||
crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
|
||||
if (crv != CKR_OK) goto loser;
|
||||
}
|
||||
|
||||
privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb);
|
||||
if (privKey == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
|
||||
privKey, &pubKey, label, sdb /*->password*/);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
|
||||
|
||||
loser:
|
||||
if (label) PORT_Free(label);
|
||||
if (privKey) nsslowkey_DestroyPrivateKey(privKey);
|
||||
if (pubKey.data) PORT_Free(pubKey.data);
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Key Object
|
||||
*/
|
||||
static CK_RV
|
||||
lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
|
||||
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
CK_KEY_TYPE key_type;
|
||||
|
||||
/* get the key type */
|
||||
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
switch (objclass) {
|
||||
case CKO_PUBLIC_KEY:
|
||||
return lg_createPublicKeyObject(sdb,key_type,handle,templ,count);
|
||||
case CKO_PRIVATE_KEY:
|
||||
return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count);
|
||||
case CKO_SECRET_KEY:
|
||||
return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the template and create an object stored in the DB that reflects.
|
||||
* the object specified in the database.
|
||||
*/
|
||||
CK_RV
|
||||
lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
CK_RV crv;
|
||||
CK_OBJECT_CLASS objclass;
|
||||
|
||||
/* get the object class */
|
||||
crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
|
||||
if (crv != CKR_OK) {
|
||||
return crv;
|
||||
}
|
||||
|
||||
/* Now handle the specific object class.
|
||||
*/
|
||||
switch (objclass) {
|
||||
case CKO_CERTIFICATE:
|
||||
crv = lg_createCertObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_TRUST:
|
||||
crv = lg_createTrustObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_CRL:
|
||||
crv = lg_createCrlObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_NETSCAPE_SMIME:
|
||||
crv = lg_createSMimeObject(sdb,handle,templ,count);
|
||||
break;
|
||||
case CKO_PRIVATE_KEY:
|
||||
case CKO_PUBLIC_KEY:
|
||||
case CKO_SECRET_KEY:
|
||||
crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
|
||||
break;
|
||||
default:
|
||||
crv = CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Internal data structures and functions used by pkcs11.c
|
||||
*/
|
||||
#ifndef _LGDB_H_
|
||||
#define _LGDB_H_ 1
|
||||
|
||||
#include "nssilock.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "lowkeyti.h"
|
||||
#include "pkcs11t.h"
|
||||
#include "sdb.h"
|
||||
#include "cdbhdl.h"
|
||||
|
||||
|
||||
#define MULTIACCESS "multiaccess:"
|
||||
|
||||
|
||||
/* machine dependent path stuff used by dbinit.c and pk11db.c */
|
||||
#ifdef macintosh
|
||||
#define PATH_SEPARATOR ":"
|
||||
#define SECMOD_DB "Security Modules"
|
||||
#define CERT_DB_FMT "%sCertificates%s"
|
||||
#define KEY_DB_FMT "%sKey Database%s"
|
||||
#else
|
||||
#define PATH_SEPARATOR "/"
|
||||
#define SECMOD_DB "secmod.db"
|
||||
#define CERT_DB_FMT "%scert%s.db"
|
||||
#define KEY_DB_FMT "%skey%s.db"
|
||||
#endif
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
||||
/* internal utility functions used by pkcs11.c */
|
||||
extern const CK_ATTRIBUTE *lg_FindAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern CK_RV lg_Attribute2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item);
|
||||
extern CK_RV lg_Attribute2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item);
|
||||
extern CK_RV lg_PrivAttr2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw);
|
||||
extern CK_RV lg_PrivAttr2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw);
|
||||
extern CK_RV lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
CK_ULONG *out);
|
||||
extern PRBool lg_hasAttribute(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern PRBool lg_isTrue(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern PRBool lg_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
|
||||
extern char *lg_getString(CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
extern unsigned int lg_MapTrust(CK_TRUST trust, PRBool clientAuth);
|
||||
|
||||
/* clear out all the existing object ID to database key mappings.
|
||||
* used to reinit a token */
|
||||
extern CK_RV SFTK_ClearTokenKeyHashTable(SDB *sdb);
|
||||
|
||||
|
||||
extern void lg_FreeSearch(SDBFind *search);
|
||||
|
||||
NSSLOWCERTCertDBHandle *lg_getCertDB(SDB *sdb);
|
||||
NSSLOWKEYDBHandle *lg_getKeyDB(SDB *sdb);
|
||||
|
||||
const char *lg_EvaluateConfigDir(const char *configdir, char **domain);
|
||||
|
||||
|
||||
/*
|
||||
* object handle modifiers
|
||||
*/
|
||||
#define LG_TOKEN_MASK 0xc0000000L
|
||||
#define LG_TOKEN_TYPE_MASK 0x38000000L
|
||||
#define LG_TOKEN_TYPE_SHIFT 27
|
||||
/* keydb (high bit == 0) */
|
||||
#define LG_TOKEN_TYPE_PRIV 0x08000000L
|
||||
#define LG_TOKEN_TYPE_PUB 0x10000000L
|
||||
#define LG_TOKEN_TYPE_KEY 0x18000000L
|
||||
/* certdb (high bit == 1) */
|
||||
#define LG_TOKEN_TYPE_TRUST 0x20000000L
|
||||
#define LG_TOKEN_TYPE_CRL 0x28000000L
|
||||
#define LG_TOKEN_TYPE_SMIME 0x30000000L
|
||||
#define LG_TOKEN_TYPE_CERT 0x38000000L
|
||||
|
||||
#define LG_TOKEN_KRL_HANDLE (LG_TOKEN_TYPE_CRL|1)
|
||||
|
||||
#define LG_SEARCH_BLOCK_SIZE 10
|
||||
#define LG_BUF_SPACE 50
|
||||
#define LG_STRICT PR_FALSE
|
||||
|
||||
/*
|
||||
* token object utilities
|
||||
*/
|
||||
void lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle);
|
||||
PRBool lg_poisonHandle(SDB *sdb, SECItem *dbkey, CK_OBJECT_HANDLE handle);
|
||||
PRBool lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
const SECItem *lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
|
||||
CK_OBJECT_HANDLE lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class);
|
||||
SECStatus lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
|
||||
|
||||
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdbpw,
|
||||
SECItem *plainText, SECItem **cipherText);
|
||||
SECStatus lg_util_decrypt(SDB *sdbpw,
|
||||
SECItem *cipherText, SECItem **plainText);
|
||||
PLHashTable *lg_GetHashTable(SDB *sdb);
|
||||
void lg_DBLock(SDB *sdb);
|
||||
void lg_DBUnlock(SDB *sdb);
|
||||
|
||||
typedef void (*LGFreeFunc)(void *);
|
||||
|
||||
|
||||
/*
|
||||
* database functions
|
||||
*/
|
||||
|
||||
/* lg_FindObjectsInit initializes a search for token and session objects
|
||||
* that match a template. */
|
||||
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
|
||||
CK_ULONG ulCount, SDBFind **search);
|
||||
/* lg_FindObjects continues a search for token and session objects
|
||||
* that match a template, obtaining additional object handles. */
|
||||
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
|
||||
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
|
||||
CK_ULONG *pulObjectCount);
|
||||
|
||||
/* lg_FindObjectsFinal finishes a search for token and session objects. */
|
||||
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search);
|
||||
|
||||
/* lg_CreateObject parses the template and create an object stored in the
|
||||
* DB that reflects the object specified in the template. */
|
||||
CK_RV lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count);
|
||||
|
||||
CK_RV lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
|
||||
const CK_ATTRIBUTE *template, CK_ULONG count);
|
||||
CK_RV lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id);
|
||||
|
||||
CK_RV lg_Close(SDB *sdb);
|
||||
CK_RV lg_Reset(SDB *sdb);
|
||||
|
||||
/*
|
||||
* The old database doesn't share and doesn't support
|
||||
* transactions.
|
||||
*/
|
||||
CK_RV lg_Begin(SDB *sdb);
|
||||
CK_RV lg_Commit(SDB *sdb);
|
||||
CK_RV lg_Abort(SDB *sdb);
|
||||
CK_RV lg_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry);
|
||||
CK_RV lg_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _LGDB_H_ */
|
||||
@@ -1,64 +0,0 @@
|
||||
;+#
|
||||
;+# ***** BEGIN LICENSE BLOCK *****
|
||||
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;+#
|
||||
;+# The contents of this file are subject to the Mozilla Public License Version
|
||||
;+# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
;+# the License. You may obtain a copy of the License at
|
||||
;+# http://www.mozilla.org/MPL/
|
||||
;+#
|
||||
;+# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
;+# for the specific language governing rights and limitations under the
|
||||
;+# License.
|
||||
;+#
|
||||
;+# The Original Code is the Netscape security libraries.
|
||||
;+#
|
||||
;+# The Initial Developer of the Original Code is
|
||||
;+# Netscape Communications Corporation.
|
||||
;+# Portions created by the Initial Developer are Copyright (C) 2000
|
||||
;+# the Initial Developer. All Rights Reserved.
|
||||
;+#
|
||||
;+# Contributor(s):
|
||||
;+# Dr Stephen Henson <stephen.henson@gemplus.com>
|
||||
;+#
|
||||
;+# Alternatively, the contents of this file may be used under the terms of
|
||||
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
;+# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
;+# of those above. If you wish to allow use of your version of this file only
|
||||
;+# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
;+# use your version of this file under the terms of the MPL, indicate your
|
||||
;+# decision by deleting the provisions above and replace them with the notice
|
||||
;+# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
;+# the provisions above, a recipient may use your version of this file under
|
||||
;+# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;+#
|
||||
;+# ***** END LICENSE BLOCK *****
|
||||
;+#
|
||||
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
|
||||
;+# 1. For all unix platforms, the string ";-" means "remove this line"
|
||||
;+# 2. For all unix platforms, the string " DATA " will be removed from any
|
||||
;+# line on which it occurs.
|
||||
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
|
||||
;+# On AIX, lines containing ";+" will be removed.
|
||||
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
|
||||
;+# 5. For all unix platforms, after the above processing has taken place,
|
||||
;+# all characters after the first ";" on the line will be removed.
|
||||
;+# And for AIX, the first ";" will also be removed.
|
||||
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
|
||||
;+# directives are hidden behind ";", ";+", and ";-"
|
||||
;+LGDBM_3.12 { # NSS 3.12 release
|
||||
;+ global:
|
||||
LIBRARY lgdbm3 ;-
|
||||
EXPORTS ;-
|
||||
legacy_Open;
|
||||
legacy_Shutdown;
|
||||
legacy_ReadSecmodDB;
|
||||
legacy_ReleaseSecmodDBData;
|
||||
legacy_AddSecmodDB;
|
||||
legacy_DeleteSecmodDB;
|
||||
legacy_SetCryptFunctions;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
@@ -1,144 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Internal PKCS #11 functions. Should only be called by pkcs11.c
|
||||
*/
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "pcert.h"
|
||||
#include "lowkeyi.h"
|
||||
|
||||
/*
|
||||
* remove an object.
|
||||
*/
|
||||
CK_RV
|
||||
lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
SECStatus rv;
|
||||
NSSLOWCERTCertificate *cert;
|
||||
NSSLOWCERTCertTrust tmptrust;
|
||||
PRBool isKrl;
|
||||
NSSLOWKEYDBHandle *keyHandle;
|
||||
NSSLOWCERTCertDBHandle *certHandle;
|
||||
const SECItem *dbKey;
|
||||
|
||||
object_id &= ~LG_TOKEN_MASK;
|
||||
dbKey = lg_lookupTokenKeyByHandle(sdb,object_id);
|
||||
if (dbKey == NULL) {
|
||||
return CKR_OBJECT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
/* remove the objects from the real data base */
|
||||
switch (object_id & LG_TOKEN_TYPE_MASK) {
|
||||
case LG_TOKEN_TYPE_PRIV:
|
||||
case LG_TOKEN_TYPE_KEY:
|
||||
/* KEYID is the public KEY for DSA and DH, and the MODULUS for
|
||||
* RSA */
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (!keyHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
rv = nsslowkey_DeleteKey(keyHandle, dbKey);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
}
|
||||
break;
|
||||
case LG_TOKEN_TYPE_PUB:
|
||||
break; /* public keys only exist at the behest of the priv key */
|
||||
case LG_TOKEN_TYPE_CERT:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
cert = nsslowcert_FindCertByKey(certHandle,dbKey);
|
||||
if (cert == NULL) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
rv = nsslowcert_DeletePermCertificate(cert);
|
||||
if (rv != SECSuccess) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
}
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
break;
|
||||
case LG_TOKEN_TYPE_CRL:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
isKrl = (PRBool) (object_id == LG_TOKEN_KRL_HANDLE);
|
||||
rv = nsslowcert_DeletePermCRL(certHandle, dbKey, isKrl);
|
||||
if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
case LG_TOKEN_TYPE_TRUST:
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (!certHandle) {
|
||||
crv = CKR_TOKEN_WRITE_PROTECTED;
|
||||
break;
|
||||
}
|
||||
cert = nsslowcert_FindCertByKey(certHandle, dbKey);
|
||||
if (cert == NULL) {
|
||||
crv = CKR_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
tmptrust = *cert->trust;
|
||||
tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
|
||||
tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
|
||||
rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
|
||||
if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lg_DBLock(sdb);
|
||||
lg_deleteTokenKeyByHandle(sdb,object_id);
|
||||
lg_DBUnlock(sdb);
|
||||
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,941 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "secitem.h"
|
||||
#include "pkcs11.h"
|
||||
#include "lgdb.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "pcert.h"
|
||||
#include "blapi.h"
|
||||
|
||||
#include "keydbi.h"
|
||||
|
||||
/*
|
||||
* This code maps PKCS #11 Finds to legacy database searches. This code
|
||||
* was orginally in pkcs11.c in previous versions of NSS.
|
||||
*/
|
||||
|
||||
struct SDBFindStr {
|
||||
CK_OBJECT_HANDLE *handles;
|
||||
int size;
|
||||
int index;
|
||||
int array_size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* free a search structure
|
||||
*/
|
||||
void
|
||||
lg_FreeSearch(SDBFind *search)
|
||||
{
|
||||
if (search->handles) {
|
||||
PORT_Free(search->handles);
|
||||
}
|
||||
PORT_Free(search);
|
||||
}
|
||||
|
||||
void
|
||||
lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
if (search->handles == NULL) {
|
||||
return;
|
||||
}
|
||||
if (search->size >= search->array_size) {
|
||||
search->array_size += LG_SEARCH_BLOCK_SIZE;
|
||||
search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
|
||||
sizeof(CK_OBJECT_HANDLE)* search->array_size);
|
||||
if (search->handles == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
search->handles[search->size] = handle;
|
||||
search->size++;
|
||||
}
|
||||
|
||||
/*
|
||||
* find any certs that may match the template and load them.
|
||||
*/
|
||||
#define LG_CERT 0x00000001
|
||||
#define LG_TRUST 0x00000002
|
||||
#define LG_CRL 0x00000004
|
||||
#define LG_SMIME 0x00000008
|
||||
#define LG_PRIVATE 0x00000010
|
||||
#define LG_PUBLIC 0x00000020
|
||||
#define LG_KEY 0x00000040
|
||||
|
||||
/*
|
||||
* structure to collect key handles.
|
||||
*/
|
||||
typedef struct lgEntryDataStr {
|
||||
SDB *sdb;
|
||||
SDBFind *searchHandles;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
} lgEntryData;
|
||||
|
||||
|
||||
static SECStatus
|
||||
lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
|
||||
{
|
||||
lgEntryData *crlData;
|
||||
CK_OBJECT_HANDLE class_handle;
|
||||
SDB *sdb;
|
||||
|
||||
crlData = (lgEntryData *)arg;
|
||||
sdb = crlData->sdb;
|
||||
|
||||
class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
|
||||
LG_TOKEN_KRL_HANDLE;
|
||||
if (lg_tokenMatch(sdb, key, class_handle,
|
||||
crlData->template, crlData->templ_count)) {
|
||||
lg_addHandle(crlData->searchHandles,
|
||||
lg_mkHandle(sdb,key,class_handle));
|
||||
}
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl,
|
||||
unsigned long classFlags, SDBFind *search,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) {
|
||||
return;
|
||||
}
|
||||
if (derSubject->data != NULL) {
|
||||
certDBEntryRevocation *crl =
|
||||
nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
|
||||
|
||||
if (crl != NULL) {
|
||||
lg_addHandle(search, lg_mkHandle(sdb, derSubject,
|
||||
isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)crl);
|
||||
}
|
||||
} else {
|
||||
lgEntryData crlData;
|
||||
|
||||
/* traverse */
|
||||
crlData.sdb = sdb;
|
||||
crlData.searchHandles = search;
|
||||
crlData.template = pTemplate;
|
||||
crlData.templ_count = ulCount;
|
||||
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
|
||||
lg_crl_collect, (void *)&crlData);
|
||||
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
|
||||
lg_crl_collect, (void *)&crlData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* structure to collect key handles.
|
||||
*/
|
||||
typedef struct lgKeyDataStr {
|
||||
SDB *sdb;
|
||||
NSSLOWKEYDBHandle *keyHandle;
|
||||
SDBFind *searchHandles;
|
||||
SECItem *id;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
unsigned long classFlags;
|
||||
PRBool strict;
|
||||
} lgKeyData;
|
||||
|
||||
static PRBool
|
||||
isSecretKey(NSSLOWKEYPrivateKey *privKey)
|
||||
{
|
||||
if (privKey->keyType == NSSLOWKEYRSAKey &&
|
||||
privKey->u.rsa.publicExponent.len == 1 &&
|
||||
privKey->u.rsa.publicExponent.data[0] == 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SECStatus
|
||||
lg_key_collect(DBT *key, DBT *data, void *arg)
|
||||
{
|
||||
lgKeyData *keyData;
|
||||
NSSLOWKEYPrivateKey *privKey = NULL;
|
||||
SECItem tmpDBKey;
|
||||
SDB *sdb;
|
||||
unsigned long classFlags;
|
||||
|
||||
keyData = (lgKeyData *)arg;
|
||||
sdb = keyData->sdb;
|
||||
classFlags = keyData->classFlags;
|
||||
|
||||
tmpDBKey.data = key->data;
|
||||
tmpDBKey.len = key->size;
|
||||
tmpDBKey.type = siBuffer;
|
||||
|
||||
PORT_Assert(keyData->keyHandle);
|
||||
if (!keyData->strict && keyData->id) {
|
||||
SECItem result;
|
||||
PRBool haveMatch= PR_FALSE;
|
||||
unsigned char hashKey[SHA1_LENGTH];
|
||||
result.data = hashKey;
|
||||
result.len = sizeof(hashKey);
|
||||
|
||||
if (keyData->id->len == 0) {
|
||||
/* Make sure this isn't a LG_KEY */
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
|
||||
&tmpDBKey, keyData->sdb/*->password*/);
|
||||
if (privKey) {
|
||||
/* turn off the unneeded class flags */
|
||||
classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE|LG_PUBLIC) :
|
||||
~LG_KEY;
|
||||
haveMatch = (PRBool)
|
||||
((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
} else {
|
||||
SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
|
||||
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
|
||||
if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
|
||||
/* This is a fix for backwards compatibility. The key
|
||||
* database indexes private keys by the public key, and
|
||||
* versions of NSS prior to 3.4 stored the public key as
|
||||
* a signed integer. The public key is now treated as an
|
||||
* unsigned integer, with no leading zero. In order to
|
||||
* correctly compute the hash of an old key, it is necessary
|
||||
* to fallback and detect the leading zero.
|
||||
*/
|
||||
SHA1_HashBuf(hashKey,
|
||||
(unsigned char *)key->data + 1, key->size - 1);
|
||||
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
|
||||
}
|
||||
}
|
||||
if (haveMatch) {
|
||||
if (classFlags & LG_PRIVATE) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
|
||||
}
|
||||
if (classFlags & LG_PUBLIC) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
|
||||
}
|
||||
if (classFlags & LG_KEY) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
|
||||
keyData->sdb/*->password*/);
|
||||
if ( privKey == NULL ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (isSecretKey(privKey)) {
|
||||
if ((classFlags & LG_KEY) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
|
||||
}
|
||||
} else {
|
||||
if ((classFlags & LG_PRIVATE) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
|
||||
}
|
||||
if ((classFlags & LG_PUBLIC) &&
|
||||
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
|
||||
keyData->template, keyData->templ_count)) {
|
||||
lg_addHandle(keyData->searchHandles,
|
||||
lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if ( privKey ) {
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchKeys(SDB *sdb, SECItem *key_id,
|
||||
unsigned long classFlags, SDBFind *search, PRBool mustStrict,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
|
||||
{
|
||||
NSSLOWKEYDBHandle *keyHandle = NULL;
|
||||
NSSLOWKEYPrivateKey *privKey;
|
||||
lgKeyData keyData;
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
keyHandle = lg_getKeyDB(sdb);
|
||||
if (keyHandle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_id->data) {
|
||||
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
|
||||
if (privKey) {
|
||||
if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
|
||||
lg_addHandle(search,
|
||||
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
|
||||
found = PR_TRUE;
|
||||
}
|
||||
nsslowkey_DestroyPrivateKey(privKey);
|
||||
}
|
||||
/* don't do the traversal if we have an up to date db */
|
||||
if (keyHandle->version != 3) {
|
||||
goto loser;
|
||||
}
|
||||
/* don't do the traversal if it can't possibly be the correct id */
|
||||
/* all soft token id's are SHA1_HASH_LEN's */
|
||||
if (key_id->len != SHA1_LENGTH) {
|
||||
goto loser;
|
||||
}
|
||||
if (found) {
|
||||
/* if we already found some keys, don't do the traversal */
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
keyData.sdb = sdb;
|
||||
keyData.keyHandle = keyHandle;
|
||||
keyData.searchHandles = search;
|
||||
keyData.id = key_id;
|
||||
keyData.template = pTemplate;
|
||||
keyData.templ_count = ulCount;
|
||||
keyData.classFlags = classFlags;
|
||||
keyData.strict = mustStrict ? mustStrict : LG_STRICT;
|
||||
|
||||
nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
|
||||
|
||||
loser:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* structure to collect certs into
|
||||
*/
|
||||
typedef struct lgCertDataStr {
|
||||
SDB *sdb;
|
||||
int cert_count;
|
||||
int max_cert_count;
|
||||
NSSLOWCERTCertificate **certs;
|
||||
const CK_ATTRIBUTE *template;
|
||||
CK_ULONG templ_count;
|
||||
unsigned long classFlags;
|
||||
PRBool strict;
|
||||
} lgCertData;
|
||||
|
||||
/*
|
||||
* collect all the certs from the traverse call.
|
||||
*/
|
||||
static SECStatus
|
||||
lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
|
||||
{
|
||||
lgCertData *cd = (lgCertData *)arg;
|
||||
|
||||
if (cert == NULL) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
if (cd->certs == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (cd->strict) {
|
||||
if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
|
||||
&cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
|
||||
return SECSuccess;
|
||||
}
|
||||
if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
|
||||
&cert->certKey, LG_TOKEN_TYPE_TRUST,
|
||||
cd->template, cd->templ_count)) {
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate more space if we need it. This should only happen in
|
||||
* the general traversal case */
|
||||
if (cd->cert_count >= cd->max_cert_count) {
|
||||
int size;
|
||||
cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
|
||||
size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
|
||||
cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
|
||||
if (cd->certs == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* provide impedence matching ... */
|
||||
static SECStatus
|
||||
lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
|
||||
{
|
||||
return lg_cert_collect(cert, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
|
||||
{
|
||||
if (cert == NULL) {
|
||||
return;
|
||||
}
|
||||
if (certData->strict &&
|
||||
!lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT,
|
||||
certData->template,certData->templ_count)) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return;
|
||||
}
|
||||
certData->certs = (NSSLOWCERTCertificate **)
|
||||
PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
|
||||
if (certData->certs == NULL) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
return;
|
||||
}
|
||||
certData->certs[0] = cert;
|
||||
certData->cert_count = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
lg_CertSetupData(lgCertData *certData,int count)
|
||||
{
|
||||
certData->max_cert_count = count;
|
||||
|
||||
if (certData->max_cert_count <= 0) {
|
||||
return;
|
||||
}
|
||||
certData->certs = (NSSLOWCERTCertificate **)
|
||||
PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name,
|
||||
SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
|
||||
SECItem *email,
|
||||
unsigned long classFlags, SDBFind *handles,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
lgCertData certData;
|
||||
int i;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) return;
|
||||
|
||||
certData.sdb = sdb;
|
||||
certData.max_cert_count = 0;
|
||||
certData.certs = NULL;
|
||||
certData.cert_count = 0;
|
||||
certData.template = pTemplate;
|
||||
certData.templ_count = ulCount;
|
||||
certData.classFlags = classFlags;
|
||||
certData.strict = LG_STRICT;
|
||||
|
||||
|
||||
/*
|
||||
* Find the Cert.
|
||||
*/
|
||||
if (derCert->data != NULL) {
|
||||
NSSLOWCERTCertificate *cert =
|
||||
nsslowcert_FindCertByDERCert(certHandle,derCert);
|
||||
lg_searchSingleCert(&certData,cert);
|
||||
} else if (name->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(name->len+1);
|
||||
int count;
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,name->data,name->len);
|
||||
tmp_name[name->len] = 0;
|
||||
|
||||
count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
|
||||
lg_cert_collect, &certData);
|
||||
PORT_Free(tmp_name);
|
||||
} else if (derSubject->data != NULL) {
|
||||
int count;
|
||||
|
||||
count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
|
||||
lg_cert_collect, &certData);
|
||||
} else if ((issuerSN->derIssuer.data != NULL) &&
|
||||
(issuerSN->serialNumber.data != NULL)) {
|
||||
if (classFlags & LG_CERT) {
|
||||
NSSLOWCERTCertificate *cert =
|
||||
nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
|
||||
|
||||
lg_searchSingleCert(&certData,cert);
|
||||
}
|
||||
if (classFlags & LG_TRUST) {
|
||||
NSSLOWCERTTrust *trust =
|
||||
nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
|
||||
|
||||
if (trust) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
|
||||
nsslowcert_DestroyTrust(trust);
|
||||
}
|
||||
}
|
||||
} else if (email->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(email->len+1);
|
||||
certDBEntrySMime *entry = NULL;
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,email->data,email->len);
|
||||
tmp_name[email->len] = 0;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
|
||||
if (entry) {
|
||||
int count;
|
||||
SECItem *subjectName = &entry->subjectName;
|
||||
|
||||
count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
|
||||
lg_CertSetupData(&certData,count);
|
||||
nsslowcert_TraversePermCertsForSubject(certHandle, subjectName,
|
||||
lg_cert_collect, &certData);
|
||||
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(tmp_name);
|
||||
} else {
|
||||
/* we aren't filtering the certs, we are working on all, so turn
|
||||
* on the strict filters. */
|
||||
certData.strict = PR_TRUE;
|
||||
lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
|
||||
nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
|
||||
}
|
||||
|
||||
/*
|
||||
* build the handles
|
||||
*/
|
||||
for (i=0 ; i < certData.cert_count ; i++) {
|
||||
NSSLOWCERTCertificate *cert = certData.certs[i];
|
||||
|
||||
/* if we filtered it would have been on the stuff above */
|
||||
if (classFlags & LG_CERT) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
|
||||
}
|
||||
if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
|
||||
}
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
}
|
||||
|
||||
if (certData.certs) PORT_Free(certData.certs);
|
||||
return;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
|
||||
{
|
||||
lgEntryData *smimeData;
|
||||
SDB *sdb;
|
||||
|
||||
smimeData = (lgEntryData *)arg;
|
||||
sdb = smimeData->sdb;
|
||||
|
||||
if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
|
||||
smimeData->template, smimeData->templ_count)) {
|
||||
lg_addHandle(smimeData->searchHandles,
|
||||
lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
|
||||
}
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
static void
|
||||
lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certHandle = NULL;
|
||||
certDBEntrySMime *entry;
|
||||
|
||||
certHandle = lg_getCertDB(sdb);
|
||||
if (certHandle == NULL) return;
|
||||
|
||||
if (email->data != NULL) {
|
||||
char *tmp_name = (char*)PORT_Alloc(email->len+1);
|
||||
|
||||
if (tmp_name == NULL) {
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(tmp_name,email->data,email->len);
|
||||
tmp_name[email->len] = 0;
|
||||
|
||||
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
|
||||
if (entry) {
|
||||
SECItem emailKey;
|
||||
|
||||
emailKey.data = (unsigned char *)tmp_name;
|
||||
emailKey.len = PORT_Strlen(tmp_name)+1;
|
||||
emailKey.type = 0;
|
||||
lg_addHandle(handles,
|
||||
lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
|
||||
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
|
||||
}
|
||||
PORT_Free(tmp_name);
|
||||
} else {
|
||||
/* traverse */
|
||||
lgEntryData smimeData;
|
||||
|
||||
/* traverse */
|
||||
smimeData.sdb = sdb;
|
||||
smimeData.searchHandles = handles;
|
||||
smimeData.template = pTemplate;
|
||||
smimeData.templ_count = ulCount;
|
||||
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
|
||||
lg_smime_collect, (void *)&smimeData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
lg_searchTokenList(SDB *sdb, SDBFind *search,
|
||||
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
|
||||
{
|
||||
int i;
|
||||
PRBool isKrl = PR_FALSE;
|
||||
SECItem derCert = { siBuffer, NULL, 0 };
|
||||
SECItem derSubject = { siBuffer, NULL, 0 };
|
||||
SECItem name = { siBuffer, NULL, 0 };
|
||||
SECItem email = { siBuffer, NULL, 0 };
|
||||
SECItem key_id = { siBuffer, NULL, 0 };
|
||||
SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
|
||||
SECItem cert_md5_hash = { siBuffer, NULL, 0 };
|
||||
NSSLOWCERTIssuerAndSN issuerSN = {
|
||||
{ siBuffer, NULL, 0 },
|
||||
{ siBuffer, NULL, 0 }
|
||||
};
|
||||
SECItem *copy = NULL;
|
||||
CK_CERTIFICATE_TYPE certType;
|
||||
CK_OBJECT_CLASS objectClass;
|
||||
CK_RV crv;
|
||||
unsigned long classFlags =
|
||||
LG_CERT|LG_TRUST|LG_PRIVATE|LG_PUBLIC|LG_KEY|LG_SMIME|LG_CRL;
|
||||
|
||||
if (lg_getCertDB(sdb) == NULL) {
|
||||
classFlags = LG_PRIVATE|LG_KEY;
|
||||
} else {
|
||||
classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for things to search on token objects for. If the right options
|
||||
* are specified, we can use them as direct indeces into the database
|
||||
* (rather than using linear searches. We can also use the attributes to
|
||||
* limit the kinds of objects we are searching for. Later we can use this
|
||||
* array to filter the remaining objects more finely.
|
||||
*/
|
||||
for (i=0 ;classFlags && i < (int)ulCount; i++) {
|
||||
|
||||
switch (pTemplate[i].type) {
|
||||
case CKA_SUBJECT:
|
||||
copy = &derSubject;
|
||||
classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
|
||||
break;
|
||||
case CKA_ISSUER:
|
||||
copy = &issuerSN.derIssuer;
|
||||
classFlags &= (LG_CERT|LG_TRUST);
|
||||
break;
|
||||
case CKA_SERIAL_NUMBER:
|
||||
copy = &issuerSN.serialNumber;
|
||||
classFlags &= (LG_CERT|LG_TRUST);
|
||||
break;
|
||||
case CKA_VALUE:
|
||||
copy = &derCert;
|
||||
classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
|
||||
break;
|
||||
case CKA_LABEL:
|
||||
copy = &name;
|
||||
break;
|
||||
case CKA_NETSCAPE_EMAIL:
|
||||
copy = &email;
|
||||
classFlags &= LG_SMIME|LG_CERT;
|
||||
break;
|
||||
case CKA_NETSCAPE_SMIME_TIMESTAMP:
|
||||
classFlags &= LG_SMIME;
|
||||
break;
|
||||
case CKA_CLASS:
|
||||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
break;;
|
||||
}
|
||||
switch (objectClass) {
|
||||
case CKO_CERTIFICATE:
|
||||
classFlags &= LG_CERT;
|
||||
break;
|
||||
case CKO_NETSCAPE_TRUST:
|
||||
classFlags &= LG_TRUST;
|
||||
break;
|
||||
case CKO_NETSCAPE_CRL:
|
||||
classFlags &= LG_CRL;
|
||||
break;
|
||||
case CKO_NETSCAPE_SMIME:
|
||||
classFlags &= LG_SMIME;
|
||||
break;
|
||||
case CKO_PRIVATE_KEY:
|
||||
classFlags &= LG_PRIVATE;
|
||||
break;
|
||||
case CKO_PUBLIC_KEY:
|
||||
classFlags &= LG_PUBLIC;
|
||||
break;
|
||||
case CKO_SECRET_KEY:
|
||||
classFlags &= LG_KEY;
|
||||
break;
|
||||
default:
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CKA_PRIVATE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
} else {
|
||||
classFlags &= ~(LG_PRIVATE|LG_KEY);
|
||||
}
|
||||
break;
|
||||
case CKA_SENSITIVE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
} else {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_TOKEN:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_CERT_SHA1_HASH:
|
||||
classFlags &= LG_TRUST;
|
||||
copy = &cert_sha1_hash; break;
|
||||
case CKA_CERT_MD5_HASH:
|
||||
classFlags &= LG_TRUST;
|
||||
copy = &cert_md5_hash; break;
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1,&certType);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
}
|
||||
classFlags &= LG_CERT;
|
||||
if (certType != CKC_X_509) {
|
||||
classFlags = 0;
|
||||
}
|
||||
break;
|
||||
case CKA_ID:
|
||||
copy = &key_id;
|
||||
classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
|
||||
break;
|
||||
case CKA_NETSCAPE_KRL:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
}
|
||||
classFlags &= LG_CRL;
|
||||
isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
|
||||
break;
|
||||
case CKA_MODIFIABLE:
|
||||
break;
|
||||
case CKA_KEY_TYPE:
|
||||
case CKA_DERIVE:
|
||||
classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
|
||||
break;
|
||||
case CKA_VERIFY_RECOVER:
|
||||
classFlags &= LG_PUBLIC;
|
||||
break;
|
||||
case CKA_SIGN_RECOVER:
|
||||
classFlags &= LG_PRIVATE;
|
||||
break;
|
||||
case CKA_ENCRYPT:
|
||||
case CKA_VERIFY:
|
||||
case CKA_WRAP:
|
||||
classFlags &= LG_PUBLIC|LG_KEY;
|
||||
break;
|
||||
case CKA_DECRYPT:
|
||||
case CKA_SIGN:
|
||||
case CKA_UNWRAP:
|
||||
case CKA_ALWAYS_SENSITIVE:
|
||||
case CKA_EXTRACTABLE:
|
||||
case CKA_NEVER_EXTRACTABLE:
|
||||
classFlags &= LG_PRIVATE|LG_KEY;
|
||||
break;
|
||||
/* can't be a certificate if it doesn't match one of the above
|
||||
* attributes */
|
||||
default:
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
if (copy) {
|
||||
copy->data = (unsigned char*)pTemplate[i].pValue;
|
||||
copy->len = pTemplate[i].ulValueLen;
|
||||
}
|
||||
copy = NULL;
|
||||
}
|
||||
|
||||
/* certs */
|
||||
if (classFlags & (LG_CERT|LG_TRUST)) {
|
||||
lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
|
||||
&issuerSN, &email,classFlags,search,
|
||||
pTemplate, ulCount);
|
||||
}
|
||||
|
||||
/* keys */
|
||||
if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
|
||||
PRBool mustStrict = ((classFlags & LG_KEY) != 0) && (name.len != 0);
|
||||
lg_searchKeys(sdb, &key_id, classFlags, search,
|
||||
mustStrict, pTemplate, ulCount);
|
||||
}
|
||||
|
||||
/* crl's */
|
||||
if (classFlags & LG_CRL) {
|
||||
lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
|
||||
pTemplate, ulCount);
|
||||
}
|
||||
/* Add S/MIME entry stuff */
|
||||
if (classFlags & LG_SMIME) {
|
||||
lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* lg_FindObjectsInit initializes a search for token and session objects
|
||||
* that match a template. */
|
||||
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
|
||||
CK_ULONG ulCount, SDBFind **retSearch)
|
||||
{
|
||||
SDBFind *search;
|
||||
CK_RV crv = CKR_OK;
|
||||
|
||||
*retSearch = NULL;
|
||||
|
||||
search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
|
||||
if (search == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
search->handles = (CK_OBJECT_HANDLE *)
|
||||
PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
|
||||
if (search->handles == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
goto loser;
|
||||
}
|
||||
search->index = 0;
|
||||
search->size = 0;
|
||||
search->array_size = LG_SEARCH_BLOCK_SIZE;
|
||||
/* FIXME - do we still need to get Login state? */
|
||||
|
||||
crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
*retSearch = search;
|
||||
return CKR_OK;
|
||||
|
||||
loser:
|
||||
if (search) {
|
||||
lg_FreeSearch(search);
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
/* lg_FindObjects continues a search for token and session objects
|
||||
* that match a template, obtaining additional object handles. */
|
||||
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
|
||||
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
|
||||
CK_ULONG *pulObjectCount)
|
||||
{
|
||||
int transfer;
|
||||
int left;
|
||||
|
||||
*pulObjectCount = 0;
|
||||
left = search->size - search->index;
|
||||
transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
|
||||
if (transfer > 0) {
|
||||
PORT_Memcpy(phObject,&search->handles[search->index],
|
||||
transfer*sizeof(CK_OBJECT_HANDLE_PTR));
|
||||
} else {
|
||||
*phObject = CK_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
search->index += transfer;
|
||||
*pulObjectCount = transfer;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* lg_FindObjectsFinal finishes a search for token and session objects. */
|
||||
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
|
||||
{
|
||||
|
||||
if (search != NULL) {
|
||||
lg_FreeSearch(search);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
@@ -1,644 +0,0 @@
|
||||
/*
|
||||
* NSS utility functions
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: lginit.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#include "lowkeyi.h"
|
||||
#include "pcert.h"
|
||||
#include "keydbi.h"
|
||||
#include "lgdb.h"
|
||||
|
||||
typedef struct LGPrivateStr {
|
||||
NSSLOWCERTCertDBHandle *certDB;
|
||||
NSSLOWKEYDBHandle *keyDB;
|
||||
PRLock *dbLock;
|
||||
PLHashTable *hashTable;
|
||||
} LGPrivate;
|
||||
|
||||
static char *
|
||||
lg_certdb_name_cb(void *arg, int dbVersion)
|
||||
{
|
||||
const char *configdir = (const char *)arg;
|
||||
const char *dbver;
|
||||
char *smpname = NULL;
|
||||
char *dbname = NULL;
|
||||
|
||||
switch (dbVersion) {
|
||||
case 8:
|
||||
dbver = "8";
|
||||
break;
|
||||
case 7:
|
||||
dbver = "7";
|
||||
break;
|
||||
case 6:
|
||||
dbver = "6";
|
||||
break;
|
||||
case 5:
|
||||
dbver = "5";
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
dbver = "";
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure we return something allocated with PORT_ so we have properly
|
||||
* matched frees at the end */
|
||||
smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
|
||||
if (smpname) {
|
||||
dbname = PORT_Strdup(smpname);
|
||||
PR_smprintf_free(smpname);
|
||||
}
|
||||
return dbname;
|
||||
}
|
||||
|
||||
static char *
|
||||
lg_keydb_name_cb(void *arg, int dbVersion)
|
||||
{
|
||||
const char *configdir = (const char *)arg;
|
||||
const char *dbver;
|
||||
char *smpname = NULL;
|
||||
char *dbname = NULL;
|
||||
|
||||
switch (dbVersion) {
|
||||
case 4:
|
||||
dbver = "4";
|
||||
break;
|
||||
case 3:
|
||||
dbver = "3";
|
||||
break;
|
||||
case 1:
|
||||
dbver = "1";
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
dbver = "";
|
||||
break;
|
||||
}
|
||||
|
||||
smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
|
||||
if (smpname) {
|
||||
dbname = PORT_Strdup(smpname);
|
||||
PR_smprintf_free(smpname);
|
||||
}
|
||||
return dbname;
|
||||
}
|
||||
|
||||
const char *
|
||||
lg_EvaluateConfigDir(const char *configdir,char **appName)
|
||||
{
|
||||
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
|
||||
char *cdir;
|
||||
|
||||
*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
|
||||
if (*appName == NULL) {
|
||||
return configdir;
|
||||
}
|
||||
cdir = *appName;
|
||||
while (*cdir && *cdir != ':') {
|
||||
cdir++;
|
||||
}
|
||||
if (*cdir == ':') {
|
||||
*cdir = 0;
|
||||
cdir++;
|
||||
}
|
||||
configdir = cdir;
|
||||
}
|
||||
return configdir;
|
||||
}
|
||||
|
||||
static int rdbmapflags(int flags);
|
||||
static rdbfunc lg_rdbfunc = NULL;
|
||||
static rdbstatusfunc lg_rdbstatusfunc = NULL;
|
||||
|
||||
/* NOTE: SHLIB_SUFFIX is defined on the command line */
|
||||
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
|
||||
|
||||
DB * rdbopen(const char *appName, const char *prefix,
|
||||
const char *type, int flags, int *status)
|
||||
{
|
||||
PRLibrary *lib;
|
||||
DB *db;
|
||||
|
||||
if (lg_rdbfunc) {
|
||||
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && lg_rdbstatusfunc) {
|
||||
*status = (*lg_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/*
|
||||
* try to open the library.
|
||||
*/
|
||||
lib = PR_LoadLibrary(RDBLIB);
|
||||
|
||||
if (!lib) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the entry points */
|
||||
lg_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
|
||||
lg_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
|
||||
if (lg_rdbfunc) {
|
||||
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
|
||||
if (!db && status && lg_rdbstatusfunc) {
|
||||
*status = (*lg_rdbstatusfunc)();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/* couldn't find the entry point, unload the library and fail */
|
||||
PR_UnloadLibrary(lib);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* the following data structures are from rdb.h.
|
||||
*/
|
||||
struct RDBStr {
|
||||
DB db;
|
||||
int (*xactstart)(DB *db);
|
||||
int (*xactdone)(DB *db, PRBool abort);
|
||||
int version;
|
||||
int (*dbinitcomplete)(DB *db);
|
||||
};
|
||||
|
||||
#define DB_RDB ((DBTYPE) 0xff)
|
||||
#define RDB_RDONLY 1
|
||||
#define RDB_RDWR 2
|
||||
#define RDB_CREATE 4
|
||||
|
||||
static int
|
||||
rdbmapflags(int flags) {
|
||||
switch (flags) {
|
||||
case NO_RDONLY:
|
||||
return RDB_RDONLY;
|
||||
case NO_RDWR:
|
||||
return RDB_RDWR;
|
||||
case NO_CREATE:
|
||||
return RDB_CREATE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
db_IsRDB(DB *db)
|
||||
{
|
||||
return (PRBool) db->type == DB_RDB;
|
||||
}
|
||||
|
||||
int
|
||||
db_BeginTransaction(DB *db)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->xactstart(db);
|
||||
}
|
||||
|
||||
int
|
||||
db_FinishTransaction(DB *db, PRBool abort)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->xactdone(db, abort);
|
||||
}
|
||||
|
||||
static DB *
|
||||
lg_getRawDB(SDB *sdb)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certDB;
|
||||
NSSLOWKEYDBHandle *keyDB;
|
||||
|
||||
certDB = lg_getCertDB(sdb);
|
||||
if (certDB) {
|
||||
return certDB->permCertDB;
|
||||
}
|
||||
keyDB = lg_getKeyDB(sdb);
|
||||
if (keyDB) {
|
||||
return keyDB->db;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Begin(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_BeginTransaction(db);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Commit(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_FinishTransaction(db, PR_FALSE);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Abort(SDB *sdb)
|
||||
{
|
||||
DB *db = lg_getRawDB(sdb);
|
||||
int ret;
|
||||
|
||||
if (db == NULL) {
|
||||
return CKR_GENERAL_ERROR; /* shouldn't happen */
|
||||
}
|
||||
ret = db_FinishTransaction(db, PR_TRUE);
|
||||
if (ret != 0) {
|
||||
return CKR_GENERAL_ERROR; /* could happen */
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
db_InitComplete(DB *db)
|
||||
{
|
||||
struct RDBStr *rdb = (struct RDBStr *)db;
|
||||
if (db->type != DB_RDB) {
|
||||
return 0;
|
||||
}
|
||||
/* we should have added a version number to the RDBS structure. Since we
|
||||
* didn't, we detect that we have and 'extended' structure if the rdbstatus
|
||||
* func exists */
|
||||
if (!lg_rdbstatusfunc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rdb->dbinitcomplete(db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SECStatus
|
||||
db_Copy(DB *dest,DB *src)
|
||||
{
|
||||
int ret;
|
||||
DBT key,data;
|
||||
ret = (*src->seq)(src, &key, &data, R_FIRST);
|
||||
if (ret) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
do {
|
||||
(void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE);
|
||||
} while ( (*src->seq)(src, &key, &data, R_NEXT) == 0);
|
||||
(void)(*dest->sync)(dest,0);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
lg_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
|
||||
NSSLOWCERTCertDBHandle **certdbPtr)
|
||||
{
|
||||
NSSLOWCERTCertDBHandle *certdb = NULL;
|
||||
CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
|
||||
SECStatus rv;
|
||||
char * name = NULL;
|
||||
char * appName = NULL;
|
||||
|
||||
if (prefix == NULL) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
configdir = lg_EvaluateConfigDir(configdir, &appName);
|
||||
|
||||
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
|
||||
if (name == NULL) goto loser;
|
||||
|
||||
certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
|
||||
if (certdb == NULL)
|
||||
goto loser;
|
||||
|
||||
certdb->ref = 1;
|
||||
/* fix when we get the DB in */
|
||||
rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
|
||||
lg_certdb_name_cb, (void *)name, PR_FALSE);
|
||||
if (rv == SECSuccess) {
|
||||
crv = CKR_OK;
|
||||
*certdbPtr = certdb;
|
||||
certdb = NULL;
|
||||
}
|
||||
loser:
|
||||
if (certdb) PR_Free(certdb);
|
||||
if (name) PR_smprintf_free(name);
|
||||
if (appName) PORT_Free(appName);
|
||||
return crv;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
lg_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
|
||||
NSSLOWKEYDBHandle **keydbPtr)
|
||||
{
|
||||
NSSLOWKEYDBHandle *keydb;
|
||||
char * name = NULL;
|
||||
char * appName = NULL;
|
||||
|
||||
if (prefix == NULL) {
|
||||
prefix = "";
|
||||
}
|
||||
configdir = lg_EvaluateConfigDir(configdir, &appName);
|
||||
|
||||
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
|
||||
if (name == NULL)
|
||||
return CKR_HOST_MEMORY;
|
||||
keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
|
||||
lg_keydb_name_cb, (void *)name);
|
||||
PR_smprintf_free(name);
|
||||
if (appName) PORT_Free(appName);
|
||||
if (keydb == NULL)
|
||||
return CKR_NETSCAPE_KEYDB_FAILED;
|
||||
*keydbPtr = keydb;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessors for the private parts of the sdb structure.
|
||||
*/
|
||||
void
|
||||
lg_DBLock(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
PR_Lock(lgdb_p->dbLock);
|
||||
}
|
||||
|
||||
void
|
||||
lg_DBUnlock(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
PR_Unlock(lgdb_p->dbLock);
|
||||
}
|
||||
|
||||
PLHashTable *
|
||||
lg_GetHashTable(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
return lgdb_p->hashTable;
|
||||
}
|
||||
|
||||
NSSLOWCERTCertDBHandle *
|
||||
lg_getCertDB(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
|
||||
return lgdb_p->certDB;
|
||||
}
|
||||
|
||||
NSSLOWKEYDBHandle *
|
||||
lg_getKeyDB(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
|
||||
return lgdb_p->keyDB;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_Close(SDB *sdb)
|
||||
{
|
||||
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
|
||||
if (lgdb_p) {
|
||||
if (lgdb_p->certDB) {
|
||||
nsslowcert_ClosePermCertDB(lgdb_p->certDB);
|
||||
} else if (lgdb_p->keyDB) {
|
||||
nsslowkey_CloseKeyDB(lgdb_p->keyDB);
|
||||
}
|
||||
if (lgdb_p->dbLock) {
|
||||
PR_DestroyLock(lgdb_p->dbLock);
|
||||
}
|
||||
if (lgdb_p->hashTable) {
|
||||
PL_HashTableDestroy(lgdb_p->hashTable);
|
||||
}
|
||||
PORT_Free(lgdb_p);
|
||||
}
|
||||
PORT_Free(sdb);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
static PLHashNumber
|
||||
lg_HashNumber(const void *key)
|
||||
{
|
||||
return (PLHashNumber) key;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* helper function to wrap a NSSLOWCERTCertDBHandle or a NSSLOWKEYDBHandle
|
||||
* with and sdb structure.
|
||||
*/
|
||||
CK_RV
|
||||
lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
|
||||
NSSLOWKEYDBHandle *keydbPtr)
|
||||
{
|
||||
SDB *sdb = NULL;
|
||||
LGPrivate *lgdb_p = NULL;
|
||||
CK_RV error = CKR_HOST_MEMORY;
|
||||
|
||||
*pSdb = NULL;
|
||||
sdb = (SDB *) PORT_Alloc(sizeof(SDB));
|
||||
if (sdb == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
lgdb_p = (LGPrivate *) PORT_Alloc(sizeof(LGPrivate));
|
||||
if (lgdb_p == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
/* invariant fields */
|
||||
lgdb_p->certDB = certdbPtr;
|
||||
lgdb_p->keyDB = keydbPtr;
|
||||
lgdb_p->dbLock = PR_NewLock();
|
||||
if (lgdb_p->dbLock == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
lgdb_p->hashTable = PL_NewHashTable(64, lg_HashNumber, PL_CompareValues,
|
||||
SECITEM_HashCompare, NULL, 0);
|
||||
if (lgdb_p->hashTable == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
sdb->sdb_type = SDB_LEGACY;
|
||||
sdb->sdb_flags = flags;
|
||||
sdb->private = lgdb_p;
|
||||
sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
|
||||
sdb->sdb_FindObjects = lg_FindObjects;
|
||||
sdb->sdb_FindObjectsFinal = lg_FindObjectsFinal;
|
||||
sdb->sdb_GetAttributeValue = lg_GetAttributeValue;
|
||||
sdb->sdb_SetAttributeValue = lg_SetAttributeValue;
|
||||
sdb->sdb_CreateObject = lg_CreateObject;
|
||||
sdb->sdb_DestroyObject = lg_DestroyObject;
|
||||
sdb->sdb_GetPWEntry = lg_GetPWEntry;
|
||||
sdb->sdb_PutPWEntry = lg_PutPWEntry;
|
||||
sdb->sdb_Begin = lg_Begin;
|
||||
sdb->sdb_Commit = lg_Commit;
|
||||
sdb->sdb_Abort = lg_Abort;
|
||||
sdb->sdb_Close = lg_Reset;
|
||||
sdb->sdb_Close = lg_Close;
|
||||
|
||||
|
||||
*pSdb = sdb;
|
||||
return CKR_OK;
|
||||
|
||||
loser:
|
||||
if (sdb) {
|
||||
PORT_Free(sdb);
|
||||
}
|
||||
if (lgdb_p) {
|
||||
if (lgdb_p->dbLock) {
|
||||
PR_DestroyLock(lgdb_p->dbLock);
|
||||
}
|
||||
if (lgdb_p->hashTable) {
|
||||
PL_HashTableDestroy(lgdb_p->hashTable);
|
||||
}
|
||||
PORT_Free(lgdb_p);
|
||||
}
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
extern SECStatus secoid_Init(void); /* util *REALLY* needs
|
||||
* to be a shared library */
|
||||
/*
|
||||
* OK there are now lots of options here, lets go through them all:
|
||||
*
|
||||
* configdir - base directory where all the cert, key, and module datbases live.
|
||||
* certPrefix - prefix added to the beginning of the cert database example: "
|
||||
* "https-server1-"
|
||||
* keyPrefix - prefix added to the beginning of the key database example: "
|
||||
* "https-server1-"
|
||||
* secmodName - name of the security module database (usually "secmod.db").
|
||||
* readOnly - Boolean: true if the databases are to be openned read only.
|
||||
* nocertdb - Don't open the cert DB and key DB's, just initialize the
|
||||
* Volatile certdb.
|
||||
* nomoddb - Don't open the security module DB, just initialize the
|
||||
* PKCS #11 module.
|
||||
* forceOpen - Continue to force initializations even if the databases cannot
|
||||
* be opened.
|
||||
*/
|
||||
CK_RV
|
||||
legacy_Open(const char *configdir, const char *certPrefix,
|
||||
const char *keyPrefix, int certVersion, int keyVersion,
|
||||
int flags, SDB **certDB, SDB **keyDB)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
PRBool readOnly = (flags == SDB_RDONLY)? PR_TRUE: PR_FALSE;
|
||||
|
||||
secoid_Init();
|
||||
nsslowcert_InitLocks();
|
||||
|
||||
if (keyDB) *keyDB = NULL;
|
||||
if (certDB) *certDB = NULL;
|
||||
|
||||
if (certDB) {
|
||||
NSSLOWCERTCertDBHandle *certdbPtr;
|
||||
|
||||
crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = lg_init(certDB, flags, certdbPtr, NULL);
|
||||
if (crv != CKR_OK) {
|
||||
nsslowcert_ClosePermCertDB(certdbPtr);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
if (keyDB) {
|
||||
NSSLOWKEYDBHandle *keydbPtr;
|
||||
|
||||
crv = lg_OpenKeyDB(configdir, keyPrefix, readOnly, &keydbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = lg_init(keyDB, flags, NULL, keydbPtr);
|
||||
if (crv != CKR_OK) {
|
||||
nsslowkey_CloseKeyDB(keydbPtr);
|
||||
goto loser;
|
||||
}
|
||||
if (certDB && *certDB) {
|
||||
LGPrivate *lgdb_p = (LGPrivate *)(*certDB)->private;
|
||||
lgdb_p->keyDB = keydbPtr;
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if (crv != CKR_OK) {
|
||||
if (keyDB && *keyDB) {
|
||||
lg_Close(*keyDB);
|
||||
*keyDB = NULL;
|
||||
}
|
||||
if (certDB && *certDB) {
|
||||
lg_Close(*certDB);
|
||||
*certDB = NULL;
|
||||
}
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
legacy_Shutdown(void)
|
||||
{
|
||||
nsslowcert_DestroyFreeLists();
|
||||
nsslowcert_DestroyGlobalLocks();
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "lgdb.h"
|
||||
#include "secerr.h"
|
||||
#include "lgglue.h"
|
||||
|
||||
/*
|
||||
* ******************** Attribute Utilities *******************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* look up and attribute structure from a type and Object structure.
|
||||
* The returned attribute is referenced and needs to be freed when
|
||||
* it is no longer needed.
|
||||
*/
|
||||
const CK_ATTRIBUTE *
|
||||
lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
if (templ[i].type == type) {
|
||||
return &templ[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return true if object has attribute
|
||||
*/
|
||||
PRBool
|
||||
lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count )
|
||||
{
|
||||
if (lg_FindAttribute(type, templ, count) == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an attribute into a SECItem. Secitem is allocated in the specified
|
||||
* arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
int len;
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
len = attribute->ulValueLen;
|
||||
|
||||
if (arena) {
|
||||
item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
|
||||
} else {
|
||||
item->data = (unsigned char *) PORT_Alloc(len);
|
||||
}
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
item->len = len;
|
||||
PORT_Memcpy(item->data, attribute->pValue, len);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
(void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
|
||||
if (item->data == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
PORT_Memcpy(item->data, attribute->pValue, item->len);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy an unsigned attribute into a SECItem. Secitem is allocated in
|
||||
* the specified arena.
|
||||
*/
|
||||
CK_RV
|
||||
lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
SECItem epki, *dest = NULL;
|
||||
SECStatus rv;
|
||||
|
||||
item->data = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
epki.data = attribute->pValue;
|
||||
epki.len = attribute->ulValueLen;
|
||||
|
||||
rv = lg_util_decrypt(sdbpw, &epki, &dest);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_USER_NOT_LOGGED_IN;
|
||||
}
|
||||
(void)SECITEM_AllocItem(arena, item, dest->len);
|
||||
if (item->data == NULL) {
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
|
||||
PORT_Memcpy(item->data, dest->data, item->len);
|
||||
SECITEM_FreeItem(dest, PR_TRUE);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
|
||||
const CK_ATTRIBUTE *templ, CK_ULONG count,
|
||||
SECItem *item, SDB *sdbpw)
|
||||
{
|
||||
return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
|
||||
}
|
||||
|
||||
/*
|
||||
* this is only valid for CK_BBOOL type attributes. Return the state
|
||||
* of that attribute.
|
||||
*/
|
||||
PRBool
|
||||
lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
PRBool tok = PR_FALSE;
|
||||
|
||||
attribute=lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) { return PR_FALSE; }
|
||||
tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a null terminated string from attribute 'type'. This string
|
||||
* is allocated and needs to be freed with PORT_Free() When complete.
|
||||
*/
|
||||
char *
|
||||
lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
char *label = NULL;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return NULL;
|
||||
|
||||
if (attribute->pValue != NULL) {
|
||||
label = (char *) PORT_Alloc(attribute->ulValueLen+1);
|
||||
if (label == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen);
|
||||
label[attribute->ulValueLen] = 0;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
|
||||
CK_ULONG count, CK_ULONG *longData)
|
||||
{
|
||||
const CK_ATTRIBUTE *attribute;
|
||||
CK_ULONG value = 0;
|
||||
const unsigned char *data;
|
||||
int i;
|
||||
|
||||
attribute = lg_FindAttribute(type, templ, count);
|
||||
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
if (attribute->ulValueLen != sizeof(CK_ULONG)) {
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
data = (const unsigned char *)attribute->pValue;
|
||||
for (i=0; i < 4; i++) {
|
||||
value |= (CK_ULONG)(data[i]) << ((3-i)*8);
|
||||
}
|
||||
|
||||
*longData = value;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************** Object Utilities *******************************
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
SECItem *item;
|
||||
PRBool rem;
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
|
||||
item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
rem = PL_HashTableRemove(hashTable,(void *)handle) ;
|
||||
if (rem && item) {
|
||||
SECITEM_FreeItem(item,PR_TRUE);
|
||||
}
|
||||
return rem ? SECSuccess : SECFailure;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
static SECStatus
|
||||
lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
|
||||
{
|
||||
PLHashEntry *entry;
|
||||
SECItem *item;
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
|
||||
item = SECITEM_DupItem(key);
|
||||
if (item == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
entry = PL_HashTableAdd(hashTable,(void *)handle,item);
|
||||
if (entry == NULL) {
|
||||
SECITEM_FreeItem(item,PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* must be called holding lg_DBLock(sdb) */
|
||||
const SECItem *
|
||||
lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
|
||||
{
|
||||
PLHashTable *hashTable= lg_GetHashTable(sdb);
|
||||
return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
|
||||
}
|
||||
|
||||
|
||||
static PRIntn
|
||||
lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
|
||||
{
|
||||
SECItem *item = (SECItem *)entry->value;
|
||||
|
||||
SECITEM_FreeItem(item, PR_TRUE);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
LG_ClearTokenKeyHashTable(SDB *sdb)
|
||||
{
|
||||
PLHashTable *hashTable;
|
||||
lg_DBLock(sdb);
|
||||
hashTable= lg_GetHashTable(sdb);
|
||||
PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
|
||||
lg_DBLock(sdb);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle Token Object stuff
|
||||
*/
|
||||
static void
|
||||
lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
PORT_Memset(key, 0, 4);
|
||||
|
||||
for (i=0; i < len-4; i += 4) {
|
||||
key[0] ^= dbkey[i];
|
||||
key[1] ^= dbkey[i+1];
|
||||
key[2] ^= dbkey[i+2];
|
||||
key[3] ^= dbkey[i+3];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a token handle for an object and record it so we can find it again */
|
||||
CK_OBJECT_HANDLE
|
||||
lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
|
||||
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
|
||||
(hashBuf[2] << 8) | hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key,dbKey)) {
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_addTokenKeyByHandle(sdb,handle,dbKey);
|
||||
lg_DBUnlock(sdb);
|
||||
return handle;
|
||||
}
|
||||
|
||||
PRBool
|
||||
lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
|
||||
{
|
||||
unsigned char hashBuf[4];
|
||||
CK_OBJECT_HANDLE handle;
|
||||
const SECItem *key;
|
||||
|
||||
handle = class;
|
||||
/* there is only one KRL, use a fixed handle for it */
|
||||
if (handle != LG_TOKEN_KRL_HANDLE) {
|
||||
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
|
||||
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
|
||||
(hashBuf[2] << 8) | hashBuf[3];
|
||||
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
|
||||
/* we have a CRL who's handle has randomly matched the reserved KRL
|
||||
* handle, increment it */
|
||||
if (handle == LG_TOKEN_KRL_HANDLE) {
|
||||
handle++;
|
||||
}
|
||||
}
|
||||
lg_DBLock(sdb);
|
||||
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
|
||||
if (SECITEM_ItemsAreEqual(key,dbKey)) {
|
||||
key->data[0] ^= 0x80;
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_TRUE;
|
||||
}
|
||||
handle++;
|
||||
}
|
||||
lg_DBUnlock(sdb);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static LGEncryptFunc lg_encrypt_stub = NULL;
|
||||
static LGDecryptFunc lg_decrypt_stub = NULL;
|
||||
|
||||
void
|
||||
legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
|
||||
{
|
||||
lg_encrypt_stub = enc;
|
||||
lg_decrypt_stub = dec;
|
||||
}
|
||||
|
||||
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb,
|
||||
SECItem *plainText, SECItem **cipherText)
|
||||
{
|
||||
if (lg_encrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
|
||||
}
|
||||
|
||||
SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
|
||||
{
|
||||
if (lg_decrypt_stub == NULL) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*lg_decrypt_stub)(sdb, cipherText, plainText);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,824 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Certificate handling code
|
||||
*
|
||||
* $Id: lowcert.c,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secder.h"
|
||||
#include "nssilock.h"
|
||||
#include "lowkeyi.h"
|
||||
#include "secasn1.h"
|
||||
#include "secoid.h"
|
||||
#include "secerr.h"
|
||||
#include "pcert.h"
|
||||
|
||||
static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
|
||||
{ SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
|
||||
SECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_BIT_STRING,
|
||||
offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
|
||||
{ 0, }
|
||||
};
|
||||
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
|
||||
{ 0, }
|
||||
};
|
||||
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
|
||||
static void
|
||||
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.rsa.modulus.type = siUnsignedInteger;
|
||||
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.dsa.publicValue.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.prime.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
|
||||
pubk->u.dsa.params.base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
pubk->u.dh.prime.type = siUnsignedInteger;
|
||||
pubk->u.dh.base.type = siUnsignedInteger;
|
||||
pubk->u.dh.publicValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
/*
|
||||
* simple cert decoder to avoid the cost of asn1 engine
|
||||
*/
|
||||
static unsigned char *
|
||||
nsslowcert_dataStart(unsigned char *buf, unsigned int length,
|
||||
unsigned int *data_length, PRBool includeTag,
|
||||
unsigned char* rettag) {
|
||||
unsigned char tag;
|
||||
unsigned int used_length= 0;
|
||||
|
||||
tag = buf[used_length++];
|
||||
|
||||
if (rettag) {
|
||||
*rettag = tag;
|
||||
}
|
||||
|
||||
/* blow out when we come to the end */
|
||||
if (tag == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*data_length = buf[used_length++];
|
||||
|
||||
if (*data_length&0x80) {
|
||||
int len_count = *data_length & 0x7f;
|
||||
|
||||
*data_length = 0;
|
||||
|
||||
while (len_count-- > 0) {
|
||||
*data_length = (*data_length << 8) | buf[used_length++];
|
||||
}
|
||||
}
|
||||
|
||||
if (*data_length > (length-used_length) ) {
|
||||
*data_length = length-used_length;
|
||||
return NULL;
|
||||
}
|
||||
if (includeTag) *data_length += used_length;
|
||||
|
||||
return (buf + (includeTag ? 0 : used_length));
|
||||
}
|
||||
|
||||
static void SetTimeType(SECItem* item, unsigned char tagtype)
|
||||
{
|
||||
switch (tagtype) {
|
||||
case SEC_ASN1_UTC_TIME:
|
||||
item->type = siUTCTime;
|
||||
break;
|
||||
|
||||
case SEC_ASN1_GENERALIZED_TIME:
|
||||
item->type = siGeneralizedTime;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_Assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
|
||||
SECItem *notBefore, SECItem *notAfter)
|
||||
{
|
||||
unsigned char tagtype;
|
||||
notBefore->data = nsslowcert_dataStart(buf,buf_length,
|
||||
¬Before->len,PR_FALSE, &tagtype);
|
||||
if (notBefore->data == NULL) return SECFailure;
|
||||
SetTimeType(notBefore, tagtype);
|
||||
buf_length -= (notBefore->data-buf) + notBefore->len;
|
||||
buf = notBefore->data + notBefore->len;
|
||||
notAfter->data = nsslowcert_dataStart(buf,buf_length,
|
||||
¬After->len,PR_FALSE, &tagtype);
|
||||
if (notAfter->data == NULL) return SECFailure;
|
||||
SetTimeType(notAfter, tagtype);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static int
|
||||
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
|
||||
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
|
||||
SECItem *valid, SECItem *subjkey, SECItem *extensions)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned int buf_length;
|
||||
unsigned char *dummy;
|
||||
unsigned int dummylen;
|
||||
|
||||
/* get past the signature wrap */
|
||||
buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
|
||||
if (buf == NULL) return SECFailure;
|
||||
/* get into the raw cert data */
|
||||
buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
|
||||
if (buf == NULL) return SECFailure;
|
||||
/* skip past any optional version number */
|
||||
if ((buf[0] & 0xa0) == 0xa0) {
|
||||
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
|
||||
if (dummy == NULL) return SECFailure;
|
||||
buf_length -= (dummy-buf) + dummylen;
|
||||
buf = dummy + dummylen;
|
||||
}
|
||||
/* serial number */
|
||||
if (derSN) {
|
||||
derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
|
||||
}
|
||||
serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
|
||||
if (serial->data == NULL) return SECFailure;
|
||||
buf_length -= (serial->data-buf) + serial->len;
|
||||
buf = serial->data + serial->len;
|
||||
/* skip the OID */
|
||||
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
|
||||
if (dummy == NULL) return SECFailure;
|
||||
buf_length -= (dummy-buf) + dummylen;
|
||||
buf = dummy + dummylen;
|
||||
/* issuer */
|
||||
issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
|
||||
if (issuer->data == NULL) return SECFailure;
|
||||
buf_length -= (issuer->data-buf) + issuer->len;
|
||||
buf = issuer->data + issuer->len;
|
||||
|
||||
/* only wanted issuer/SN */
|
||||
if (valid == NULL) {
|
||||
return SECSuccess;
|
||||
}
|
||||
/* validity */
|
||||
valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
|
||||
if (valid->data == NULL) return SECFailure;
|
||||
buf_length -= (valid->data-buf) + valid->len;
|
||||
buf = valid->data + valid->len;
|
||||
/*subject */
|
||||
subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
|
||||
if (subject->data == NULL) return SECFailure;
|
||||
buf_length -= (subject->data-buf) + subject->len;
|
||||
buf = subject->data + subject->len;
|
||||
/* subject key info */
|
||||
subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
|
||||
if (subjkey->data == NULL) return SECFailure;
|
||||
buf_length -= (subjkey->data-buf) + subjkey->len;
|
||||
buf = subjkey->data + subjkey->len;
|
||||
|
||||
extensions->data = NULL;
|
||||
extensions->len = 0;
|
||||
while (buf_length > 0) {
|
||||
/* EXTENSIONS */
|
||||
if (buf[0] == 0xa3) {
|
||||
extensions->data = nsslowcert_dataStart(buf,buf_length,
|
||||
&extensions->len, PR_FALSE, NULL);
|
||||
break;
|
||||
}
|
||||
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
|
||||
if (dummy == NULL) return SECFailure;
|
||||
buf_length -= (dummy - buf) + dummylen;
|
||||
buf = dummy + dummylen;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
|
||||
{
|
||||
int rv;
|
||||
NSSLOWCERTValidity validity;
|
||||
|
||||
rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
|
||||
&validity.notBefore,&validity.notAfter);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* convert DER not-before time */
|
||||
rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
|
||||
if (rv) {
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
/* convert DER not-after time */
|
||||
rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
|
||||
if (rv) {
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
return(SECSuccess);
|
||||
}
|
||||
|
||||
/*
|
||||
* is certa newer than certb? If one is expired, pick the other one.
|
||||
*/
|
||||
PRBool
|
||||
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
|
||||
{
|
||||
PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
|
||||
SECStatus rv;
|
||||
PRBool newerbefore, newerafter;
|
||||
|
||||
rv = nsslowcert_GetCertTimes(certa, ¬BeforeA, ¬AfterA);
|
||||
if ( rv != SECSuccess ) {
|
||||
return(PR_FALSE);
|
||||
}
|
||||
|
||||
rv = nsslowcert_GetCertTimes(certb, ¬BeforeB, ¬AfterB);
|
||||
if ( rv != SECSuccess ) {
|
||||
return(PR_TRUE);
|
||||
}
|
||||
|
||||
newerbefore = PR_FALSE;
|
||||
if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
|
||||
newerbefore = PR_TRUE;
|
||||
}
|
||||
|
||||
newerafter = PR_FALSE;
|
||||
if ( LL_CMP(notAfterA, >, notAfterB) ) {
|
||||
newerafter = PR_TRUE;
|
||||
}
|
||||
|
||||
if ( newerbefore && newerafter ) {
|
||||
return(PR_TRUE);
|
||||
}
|
||||
|
||||
if ( ( !newerbefore ) && ( !newerafter ) ) {
|
||||
return(PR_FALSE);
|
||||
}
|
||||
|
||||
/* get current time */
|
||||
now = PR_Now();
|
||||
|
||||
if ( newerbefore ) {
|
||||
/* cert A was issued after cert B, but expires sooner */
|
||||
/* if A is expired, then pick B */
|
||||
if ( LL_CMP(notAfterA, <, now ) ) {
|
||||
return(PR_FALSE);
|
||||
}
|
||||
return(PR_TRUE);
|
||||
} else {
|
||||
/* cert B was issued after cert A, but expires sooner */
|
||||
/* if B is expired, then pick A */
|
||||
if ( LL_CMP(notAfterB, <, now ) ) {
|
||||
return(PR_TRUE);
|
||||
}
|
||||
return(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#define SOFT_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena,
|
||||
SECItem *issuer, SECItem *sn, SECItem *key)
|
||||
{
|
||||
unsigned int len = sn->len + issuer->len;
|
||||
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto loser;
|
||||
}
|
||||
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
|
||||
if ( !key->data ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
key->len = len;
|
||||
/* copy the serialNumber */
|
||||
PORT_Memcpy(key->data, sn->data, sn->len);
|
||||
|
||||
/* copy the issuer */
|
||||
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
|
||||
|
||||
return(SECSuccess);
|
||||
|
||||
loser:
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
|
||||
int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
|
||||
{
|
||||
unsigned int len = sn->len + issuer->len;
|
||||
|
||||
key->data = pkcs11_allocStaticData(len, space, spaceLen);
|
||||
if ( !key->data ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
key->len = len;
|
||||
/* copy the serialNumber */
|
||||
PORT_Memcpy(key->data, sn->data, sn->len);
|
||||
|
||||
/* copy the issuer */
|
||||
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
|
||||
|
||||
return(SECSuccess);
|
||||
|
||||
loser:
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned int buf_length;
|
||||
|
||||
/* unwrap outer sequence */
|
||||
buf=nsslowcert_dataStart(derDN->data,derDN->len,&buf_length,PR_FALSE,NULL);
|
||||
if (buf == NULL) return NULL;
|
||||
|
||||
/* Walk each RDN */
|
||||
while (buf_length > 0) {
|
||||
unsigned char *rdn;
|
||||
unsigned int rdn_length;
|
||||
|
||||
/* grab next rdn */
|
||||
rdn=nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
|
||||
if (rdn == NULL) { return NULL; }
|
||||
buf_length -= (rdn - buf) + rdn_length;
|
||||
buf = rdn+rdn_length;
|
||||
|
||||
while (rdn_length > 0) {
|
||||
unsigned char *ava;
|
||||
unsigned int ava_length;
|
||||
unsigned char *oid;
|
||||
unsigned int oid_length;
|
||||
unsigned char *name;
|
||||
unsigned int name_length;
|
||||
SECItem oidItem;
|
||||
SECOidTag type;
|
||||
|
||||
/* unwrap the ava */
|
||||
ava=nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
|
||||
NULL);
|
||||
if (ava == NULL) return NULL;
|
||||
rdn_length -= (ava-rdn)+ava_length;
|
||||
rdn = ava + ava_length;
|
||||
|
||||
oid=nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
|
||||
NULL);
|
||||
if (oid == NULL) { return NULL; }
|
||||
ava_length -= (oid-ava)+oid_length;
|
||||
ava = oid+oid_length;
|
||||
|
||||
name=nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
|
||||
NULL);
|
||||
if (oid == NULL) { return NULL; }
|
||||
ava_length -= (name-ava)+name_length;
|
||||
ava = name+name_length;
|
||||
|
||||
oidItem.data = oid;
|
||||
oidItem.len = oid_length;
|
||||
type = SECOID_FindOIDTag(&oidItem);
|
||||
if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
|
||||
(type == SEC_OID_RFC1274_MAIL)) {
|
||||
/* Email is supposed to be IA5String, so no
|
||||
* translation necessary */
|
||||
char *emailAddr;
|
||||
emailAddr = (char *)pkcs11_copyStaticData(name,name_length+1,
|
||||
(unsigned char *)space,len);
|
||||
if (emailAddr) {
|
||||
emailAddr[name_length] = 0;
|
||||
}
|
||||
return emailAddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned char *exts;
|
||||
unsigned int exts_length;
|
||||
|
||||
/* unwrap the sequence */
|
||||
exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
|
||||
&exts_length, PR_FALSE, NULL);
|
||||
/* loop through extension */
|
||||
while (exts && exts_length > 0) {
|
||||
unsigned char * ext;
|
||||
unsigned int ext_length;
|
||||
unsigned char *oid;
|
||||
unsigned int oid_length;
|
||||
unsigned char *nameList;
|
||||
unsigned int nameList_length;
|
||||
SECItem oidItem;
|
||||
SECOidTag type;
|
||||
|
||||
ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
|
||||
PR_FALSE, NULL);
|
||||
if (ext == NULL) { break; }
|
||||
exts_length -= (ext - exts) + ext_length;
|
||||
exts = ext+ext_length;
|
||||
|
||||
oid=nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
|
||||
if (oid == NULL) { break; }
|
||||
ext_length -= (oid - ext) + oid_length;
|
||||
ext = oid+oid_length;
|
||||
oidItem.data = oid;
|
||||
oidItem.len = oid_length;
|
||||
type = SECOID_FindOIDTag(&oidItem);
|
||||
|
||||
/* get Alt Extension */
|
||||
if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip passed the critical flag */
|
||||
if (ext[0] == 0x01) { /* BOOLEAN */
|
||||
unsigned char *dummy;
|
||||
unsigned int dummy_length;
|
||||
dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
|
||||
PR_FALSE, NULL);
|
||||
if (dummy == NULL) { break; }
|
||||
ext_length -= (dummy - ext) + dummy_length;
|
||||
ext = dummy+dummy_length;
|
||||
}
|
||||
|
||||
|
||||
/* unwrap the name list */
|
||||
nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
|
||||
PR_FALSE, NULL);
|
||||
if (nameList == NULL) { break; }
|
||||
ext_length -= (nameList - ext) + nameList_length;
|
||||
ext = nameList+nameList_length;
|
||||
nameList = nsslowcert_dataStart(nameList, nameList_length,
|
||||
&nameList_length, PR_FALSE, NULL);
|
||||
/* loop through the name list */
|
||||
while (nameList && nameList_length > 0) {
|
||||
unsigned char *thisName;
|
||||
unsigned int thisName_length;
|
||||
|
||||
thisName = nsslowcert_dataStart(nameList, nameList_length,
|
||||
&thisName_length, PR_FALSE, NULL);
|
||||
if (thisName == NULL) { break; }
|
||||
if (nameList[0] == 0xa2) { /* DNS Name */
|
||||
SECItem dn;
|
||||
char *emailAddr;
|
||||
|
||||
dn.data = thisName;
|
||||
dn.len = thisName_length;
|
||||
emailAddr = nsslowcert_EmailName(&dn, space, len);
|
||||
if (emailAddr) {
|
||||
return emailAddr;
|
||||
}
|
||||
}
|
||||
if (nameList[0] == 0x81) { /* RFC 822name */
|
||||
char *emailAddr;
|
||||
emailAddr = (char *)pkcs11_copyStaticData(thisName,
|
||||
thisName_length+1, (unsigned char *)space,len);
|
||||
if (emailAddr) {
|
||||
emailAddr[thisName_length] = 0;
|
||||
}
|
||||
return emailAddr;
|
||||
}
|
||||
nameList_length -= (thisName-nameList) + thisName_length;
|
||||
nameList = thisName + thisName_length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
|
||||
{
|
||||
char *emailAddr = NULL;
|
||||
char *str;
|
||||
|
||||
emailAddr = nsslowcert_EmailName(&cert->derSubject,cert->emailAddrSpace,
|
||||
sizeof(cert->emailAddrSpace));
|
||||
/* couldn't find the email address in the DN, check the subject Alt name */
|
||||
if (!emailAddr && cert->extensions.data) {
|
||||
emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
|
||||
sizeof(cert->emailAddrSpace));
|
||||
}
|
||||
|
||||
|
||||
/* make it lower case */
|
||||
str = emailAddr;
|
||||
while ( str && *str ) {
|
||||
*str = tolower( *str );
|
||||
str++;
|
||||
}
|
||||
return emailAddr;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* take a DER certificate and decode it into a certificate structure
|
||||
*/
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
|
||||
{
|
||||
NSSLOWCERTCertificate *cert;
|
||||
int rv;
|
||||
|
||||
/* allocate the certificate structure */
|
||||
cert = nsslowcert_CreateCert();
|
||||
|
||||
if ( !cert ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* point to passed in DER data */
|
||||
cert->derCert = *derSignedCert;
|
||||
cert->nickname = NULL;
|
||||
cert->certKey.data = NULL;
|
||||
cert->referenceCount = 1;
|
||||
|
||||
/* decode the certificate info */
|
||||
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
|
||||
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
|
||||
&cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
|
||||
|
||||
/* cert->subjectKeyID; x509v3 subject key identifier */
|
||||
cert->subjectKeyID.data = NULL;
|
||||
cert->subjectKeyID.len = 0;
|
||||
cert->dbEntry = NULL;
|
||||
cert ->trust = NULL;
|
||||
cert ->dbhandle = NULL;
|
||||
|
||||
/* generate and save the database key for the cert */
|
||||
rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
|
||||
sizeof(cert->certKeySpace), &cert->derIssuer,
|
||||
&cert->serialNumber, &cert->certKey);
|
||||
if ( rv ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* set the nickname */
|
||||
if ( nickname == NULL ) {
|
||||
cert->nickname = NULL;
|
||||
} else {
|
||||
/* copy and install the nickname */
|
||||
cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
|
||||
sizeof(cert->nicknameSpace));
|
||||
}
|
||||
|
||||
#ifdef FIXME
|
||||
/* initialize the subjectKeyID */
|
||||
rv = cert_GetKeyID(cert);
|
||||
if ( rv != SECSuccess ) {
|
||||
goto loser;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set the email address */
|
||||
cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
|
||||
|
||||
|
||||
cert->referenceCount = 1;
|
||||
|
||||
return(cert);
|
||||
|
||||
loser:
|
||||
if (cert) {
|
||||
nsslowcert_DestroyCertificate(cert);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *
|
||||
nsslowcert_FixupEmailAddr(char *emailAddr)
|
||||
{
|
||||
char *retaddr;
|
||||
char *str;
|
||||
|
||||
if ( emailAddr == NULL ) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* copy the string */
|
||||
str = retaddr = PORT_Strdup(emailAddr);
|
||||
if ( str == NULL ) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* make it lower case */
|
||||
while ( *str ) {
|
||||
*str = tolower( *str );
|
||||
str++;
|
||||
}
|
||||
|
||||
return(retaddr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate a database key, based on serial number and issuer, from a
|
||||
* DER certificate.
|
||||
*/
|
||||
SECStatus
|
||||
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
|
||||
{
|
||||
int rv;
|
||||
NSSLOWCERTCertKey certkey;
|
||||
|
||||
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
|
||||
|
||||
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
|
||||
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if ( rv ) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
|
||||
&certkey.serialNumber, key));
|
||||
loser:
|
||||
return(SECFailure);
|
||||
}
|
||||
|
||||
NSSLOWKEYPublicKey *
|
||||
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
|
||||
{
|
||||
NSSLOWCERTSubjectPublicKeyInfo spki;
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
SECItem os;
|
||||
SECStatus rv;
|
||||
PRArenaPool *arena;
|
||||
SECOidTag tag;
|
||||
SECItem newDerSubjKeyInfo;
|
||||
|
||||
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL)
|
||||
return NULL;
|
||||
|
||||
pubk = (NSSLOWKEYPublicKey *)
|
||||
PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk == NULL) {
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pubk->arena = arena;
|
||||
PORT_Memset(&spki,0,sizeof(spki));
|
||||
|
||||
/* copy the DER into the arena, since Quick DER returns data that points
|
||||
into the DER input, which may get freed by the caller */
|
||||
rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
|
||||
if ( rv != SECSuccess ) {
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* we haven't bothered decoding the spki struct yet, do it now */
|
||||
rv = SEC_QuickDERDecodeItem(arena, &spki,
|
||||
nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert bit string length from bits to bytes */
|
||||
os = spki.subjectPublicKey;
|
||||
DER_ConvertBitString (&os);
|
||||
|
||||
tag = SECOID_GetAlgorithmTag(&spki.algorithm);
|
||||
switch ( tag ) {
|
||||
case SEC_OID_X500_RSA_ENCRYPTION:
|
||||
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
||||
pubk->keyType = NSSLOWKEYRSAKey;
|
||||
prepare_low_rsa_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_RSAPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess)
|
||||
return pubk;
|
||||
break;
|
||||
case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
||||
pubk->keyType = NSSLOWKEYDSAKey;
|
||||
prepare_low_dsa_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_DSAPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
|
||||
pubk->keyType = NSSLOWKEYDHKey;
|
||||
prepare_low_dh_pub_key_for_asn1(pubk);
|
||||
rv = SEC_QuickDERDecodeItem(arena, pubk,
|
||||
nsslowcert_DHPublicKeyTemplate, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
||||
pubk->keyType = NSSLOWKEYECKey;
|
||||
/* Since PKCS#11 directly takes the DER encoding of EC params
|
||||
* and public value, we don't need any decoding here.
|
||||
*/
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
|
||||
&spki.algorithm.parameters);
|
||||
if ( rv != SECSuccess )
|
||||
break;
|
||||
|
||||
/* Fill out the rest of the ecParams structure
|
||||
* based on the encoded params
|
||||
*/
|
||||
if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
|
||||
&pubk->u.ec.ecParams) != SECSuccess)
|
||||
break;
|
||||
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
default:
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
nsslowkey_DestroyPublicKey (pubk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,462 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "lowkeyi.h"
|
||||
#include "secoid.h"
|
||||
#include "secitem.h"
|
||||
#include "secder.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
|
||||
static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYAttribute) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
|
||||
{ SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
|
||||
SEC_AnyTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
|
||||
{ SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
|
||||
};
|
||||
/* ASN1 Templates for new decoder/encoder */
|
||||
const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,version) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
|
||||
SECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
|
||||
nsslowkey_SetOfAttributeTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
/* XXX This is just a placeholder for later when we support
|
||||
* generic curves and need full-blown support for parsing EC
|
||||
* parameters. For now, we only support named curves in which
|
||||
* EC params are simply encoded as an object ID and we don't
|
||||
* use nsslowkey_ECParamsTemplate.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
/* NOTE: The SECG specification allows the private key structure
|
||||
* to contain curve parameters but recommends that they be stored
|
||||
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
|
||||
* instead.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
|
||||
/* XXX The following template works for now since we only
|
||||
* support named curves for which the parameters are
|
||||
* encoded as an object ID. When we support generic curves,
|
||||
* we'll need to define nsslowkey_ECParamsTemplate
|
||||
*/
|
||||
#if 1
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
|
||||
SEC_ObjectIDTemplate },
|
||||
#else
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
|
||||
nsslowkey_ECParamsTemplate },
|
||||
#endif
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
|
||||
SEC_BitStringTemplate },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* smaller version of EC_FillParams. In this code, we only need
|
||||
* oid and DER data.
|
||||
*/
|
||||
SECStatus
|
||||
LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params)
|
||||
{
|
||||
SECOidTag tag;
|
||||
SECItem oid = { siBuffer, NULL, 0};
|
||||
|
||||
#if EC_DEBUG
|
||||
int i;
|
||||
|
||||
printf("Encoded params in EC_DecodeParams: ");
|
||||
for (i = 0; i < encodedParams->len; i++) {
|
||||
printf("%02x:", encodedParams->data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
oid.len = encodedParams->len - 2;
|
||||
oid.data = encodedParams->data + 2;
|
||||
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
|
||||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
params->arena = arena;
|
||||
|
||||
/* For named curves, fill out curveOID */
|
||||
params->curveOID.len = oid.len;
|
||||
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
|
||||
if (params->curveOID.data == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
memcpy(params->curveOID.data, oid.data, oid.len);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Copy all of the fields from srcParams into dstParams
|
||||
*/
|
||||
SECStatus
|
||||
LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
dstParams->arena = arena;
|
||||
rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
|
||||
&srcParams->DEREncoding);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
|
||||
&srcParams->curveOID);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
return SECFailure;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
|
||||
void
|
||||
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.rsa.modulus.type = siUnsignedInteger;
|
||||
key->u.rsa.publicExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.privateExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.prime1.type = siUnsignedInteger;
|
||||
key->u.rsa.prime2.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent1.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent2.type = siUnsignedInteger;
|
||||
key->u.rsa.coefficient.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_pqg_params_for_asn1(PQGParams *params)
|
||||
{
|
||||
params->prime.type = siUnsignedInteger;
|
||||
params->subPrime.type = siUnsignedInteger;
|
||||
params->base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.publicValue.type = siUnsignedInteger;
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
key->u.dsa.params.prime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.subPrime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dh.prime.type = siUnsignedInteger;
|
||||
key->u.dh.base.type = siUnsignedInteger;
|
||||
key->u.dh.publicValue.type = siUnsignedInteger;
|
||||
key->u.dh.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
void
|
||||
prepare_low_ecparams_for_asn1(ECParams *params)
|
||||
{
|
||||
params->DEREncoding.type = siUnsignedInteger;
|
||||
params->curveOID.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.ec.version.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
|
||||
key->u.ec.privateValue.type = siUnsignedInteger;
|
||||
key->u.ec.publicValue.type = siUnsignedInteger;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
if (privk && privk->arena) {
|
||||
PORT_FreeArena(privk->arena, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
if (pubk && pubk->arena) {
|
||||
PORT_FreeArena(pubk->arena, PR_FALSE);
|
||||
}
|
||||
}
|
||||
unsigned
|
||||
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
unsigned char b0;
|
||||
|
||||
/* interpret modulus length as key strength... in
|
||||
* fortezza that's the public key length */
|
||||
|
||||
switch (pubk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = pubk->u.rsa.modulus.data[0];
|
||||
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
|
||||
unsigned char b0;
|
||||
|
||||
switch (privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = privk->u.rsa.modulus.data[0];
|
||||
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSSLOWKEYPublicKey *
|
||||
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
PLArenaPool *arena;
|
||||
|
||||
|
||||
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
case NSSLOWKEYNullKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof (NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
if (privk->keyType == NSSLOWKEYNullKey) return pubk;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
|
||||
&privk->u.rsa.modulus);
|
||||
if (rv == SECSuccess) {
|
||||
rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
|
||||
&privk->u.rsa.publicExponent);
|
||||
if (rv == SECSuccess)
|
||||
return pubk;
|
||||
}
|
||||
} else {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDSAKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
|
||||
&privk->u.dsa.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
|
||||
&privk->u.dsa.params.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
|
||||
&privk->u.dsa.params.subPrime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
|
||||
&privk->u.dsa.params.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDHKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
|
||||
&privk->u.dh.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
|
||||
&privk->u.dh.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
|
||||
&privk->u.dh.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case NSSLOWKEYECKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
|
||||
&privk->u.ec.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
pubk->u.ec.ecParams.arena = arena;
|
||||
/* Copy the rest of the params */
|
||||
rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
|
||||
&(privk->u.ec.ecParams));
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/* No Fortezza in Low Key implementations (Fortezza keys aren't
|
||||
* stored in our data base */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: lowkeyi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _LOWKEYI_H_
|
||||
#define _LOWKEYI_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "pcertt.h"
|
||||
#include "lowkeyti.h"
|
||||
#include "sdb.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
|
||||
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_ecparams_for_asn1(ECParams *params);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
|
||||
|
||||
/*
|
||||
** Open a key database.
|
||||
*/
|
||||
extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
|
||||
const char *domain,
|
||||
const char *prefix,
|
||||
NSSLOWKEYDBNameFunc namecb,
|
||||
void *cbarg);
|
||||
|
||||
/*
|
||||
** Close the specified key database.
|
||||
*/
|
||||
extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
|
||||
|
||||
/*
|
||||
* Get the version number of the database
|
||||
*/
|
||||
extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
|
||||
|
||||
/*
|
||||
** Delete a key from the database
|
||||
*/
|
||||
extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
|
||||
const SECItem *pubkey);
|
||||
|
||||
/*
|
||||
** Store a key in the database, indexed by its public key modulus.
|
||||
** "pk" is the private key to store
|
||||
** "f" is a the callback function for getting the password
|
||||
** "arg" is the argument for the callback
|
||||
*/
|
||||
extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *pk,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb);
|
||||
|
||||
/* does the key for this cert exist in the database filed by modulus */
|
||||
extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWCERTCertificate *cert);
|
||||
/* does a key with this ID already exist? */
|
||||
extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
|
||||
|
||||
/*
|
||||
** Destroy a private key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
|
||||
|
||||
/*
|
||||
** Destroy a public key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
|
||||
|
||||
/*
|
||||
** Return the modulus length of "pubKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
|
||||
|
||||
|
||||
/*
|
||||
** Return the modulus length of "privKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
|
||||
|
||||
|
||||
/*
|
||||
** Convert a low private key "privateKey" into a public low key
|
||||
*/
|
||||
extern NSSLOWKEYPublicKey
|
||||
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
|
||||
|
||||
|
||||
SECStatus
|
||||
nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *privkey,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb);
|
||||
|
||||
/* Store key by modulus and specify an encryption algorithm to use.
|
||||
* handle is the pointer to the key database,
|
||||
* privkey is the private key to be stored,
|
||||
* f and arg are the function and arguments to the callback
|
||||
* to get a password,
|
||||
* algorithm is the algorithm which the privKey is to be stored.
|
||||
* A return of anything but SECSuccess indicates failure.
|
||||
*/
|
||||
extern SECStatus
|
||||
nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
|
||||
NSSLOWKEYPrivateKey *privkey,
|
||||
SECItem *pubKeyData,
|
||||
char *nickname,
|
||||
SDB *sdb,
|
||||
PRBool update);
|
||||
|
||||
/* Find key by modulus. This function is the inverse of store key
|
||||
* by modulus. An attempt to locate the key with "modulus" is
|
||||
* performed. If the key is found, the private key is returned,
|
||||
* else NULL is returned.
|
||||
* modulus is the modulus to locate
|
||||
*/
|
||||
extern NSSLOWKEYPrivateKey *
|
||||
nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
|
||||
SDB *sdb);
|
||||
|
||||
extern char *
|
||||
nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
|
||||
SECItem *modulus, SDB *sdb);
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/*
|
||||
* smaller version of EC_FillParams. In this code, we only need
|
||||
* oid and DER data.
|
||||
*/
|
||||
SECStatus LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
|
||||
ECParams *params);
|
||||
|
||||
/* Copy all of the fields from srcParams into dstParams */
|
||||
SECStatus LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
||||
const ECParams *srcParams);
|
||||
#endif
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _LOWKEYI_H_ */
|
||||
@@ -1,161 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef _LOWKEYTI_H_
|
||||
#define _LOWKEYTI_H_ 1
|
||||
|
||||
#include "blapit.h"
|
||||
#include "prtypes.h"
|
||||
#include "plarena.h"
|
||||
#include "secitem.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
|
||||
/*
|
||||
* a key in/for the data base
|
||||
*/
|
||||
struct NSSLOWKEYDBKeyStr {
|
||||
PLArenaPool *arena;
|
||||
int version;
|
||||
char *nickname;
|
||||
SECItem salt;
|
||||
SECItem derPK;
|
||||
};
|
||||
typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
|
||||
|
||||
typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
|
||||
|
||||
#ifdef NSS_USE_KEY4_DB
|
||||
#define NSSLOWKEY_DB_FILE_VERSION 4
|
||||
#else
|
||||
#define NSSLOWKEY_DB_FILE_VERSION 3
|
||||
#endif
|
||||
|
||||
#define NSSLOWKEY_VERSION 0 /* what we *create* */
|
||||
|
||||
/*
|
||||
** Typedef for callback to get a password "key".
|
||||
*/
|
||||
extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
|
||||
extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
|
||||
|
||||
/*
|
||||
* PKCS #8 attributes
|
||||
*/
|
||||
struct NSSLOWKEYAttributeStr {
|
||||
SECItem attrType;
|
||||
SECItem *attrValue;
|
||||
};
|
||||
typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
|
||||
|
||||
/*
|
||||
** A PKCS#8 private key info object
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyInfoStr {
|
||||
PLArenaPool *arena;
|
||||
SECItem version;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem privateKey;
|
||||
NSSLOWKEYAttribute **attributes;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
|
||||
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
|
||||
|
||||
/*
|
||||
** A PKCS#8 private key info object
|
||||
*/
|
||||
struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
|
||||
PLArenaPool *arena;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem encryptedData;
|
||||
};
|
||||
typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
|
||||
|
||||
|
||||
typedef enum {
|
||||
NSSLOWKEYNullKey = 0,
|
||||
NSSLOWKEYRSAKey = 1,
|
||||
NSSLOWKEYDSAKey = 2,
|
||||
NSSLOWKEYDHKey = 4,
|
||||
NSSLOWKEYECKey = 5
|
||||
} NSSLOWKEYType;
|
||||
|
||||
/*
|
||||
** An RSA public key object.
|
||||
*/
|
||||
struct NSSLOWKEYPublicKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType ;
|
||||
union {
|
||||
RSAPublicKey rsa;
|
||||
DSAPublicKey dsa;
|
||||
DHPublicKey dh;
|
||||
ECPublicKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
|
||||
|
||||
/*
|
||||
** Low Level private key object
|
||||
** This is only used by the raw Crypto engines (crypto), keydb (keydb),
|
||||
** and PKCS #11. Everyone else uses the high level key structure.
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType;
|
||||
union {
|
||||
RSAPrivateKey rsa;
|
||||
DSAPrivateKey dsa;
|
||||
DHPrivateKey dh;
|
||||
ECPrivateKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
|
||||
|
||||
#endif /* _LOWKEYTI_H_ */
|
||||
@@ -1,68 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
CORE_DEPTH = ../../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
REQUIRES = dbm
|
||||
|
||||
LIBRARY_NAME = lgdbm
|
||||
LIBRARY_VERSION = 3
|
||||
MAPFILE = $(OBJDIR)/lgdbm.def
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
|
||||
|
||||
|
||||
CSRCS = \
|
||||
dbmshim.c \
|
||||
keydb.c \
|
||||
lgattr.c \
|
||||
lgcreate.c \
|
||||
lgdestroy.c \
|
||||
lgfind.c \
|
||||
lginit.c \
|
||||
lgutil.c \
|
||||
lowcert.c \
|
||||
lowkey.c \
|
||||
pcertdb.c \
|
||||
pk11db.c \
|
||||
$(NULL)
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
DEFINES += -DNSS_ENABLE_ECC
|
||||
endif
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _PCERTDB_H_
|
||||
#define _PCERTDB_H_
|
||||
|
||||
#include "plarena.h"
|
||||
#include "prlong.h"
|
||||
#include "pcertt.h"
|
||||
|
||||
#include "lowkeyti.h" /* for struct NSSLOWKEYPublicKeyStr */
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* initialize any global certificate locks
|
||||
*/
|
||||
SECStatus nsslowcert_InitLocks(void);
|
||||
|
||||
/*
|
||||
** Add a DER encoded certificate to the permanent database.
|
||||
** "derCert" is the DER encoded certificate.
|
||||
** "nickname" is the nickname to use for the cert
|
||||
** "trust" is the trust parameters for the cert
|
||||
*/
|
||||
SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle,
|
||||
NSSLOWCERTCertificate *cert,
|
||||
char *nickname, NSSLOWCERTCertTrust *trust);
|
||||
SECStatus nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle,
|
||||
NSSLOWCERTCertificate *cert, char *nickname);
|
||||
|
||||
SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert);
|
||||
|
||||
typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert,
|
||||
SECItem *k, void *pdata);
|
||||
/*
|
||||
** Traverse the entire permanent database, and pass the certs off to a
|
||||
** user supplied function.
|
||||
** "certfunc" is the user function to call for each certificate
|
||||
** "udata" is the user's data, which is passed through to "certfunc"
|
||||
*/
|
||||
SECStatus
|
||||
nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle,
|
||||
PermCertCallback certfunc,
|
||||
void *udata );
|
||||
|
||||
PRBool
|
||||
nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle);
|
||||
|
||||
certDBEntryRevocation *
|
||||
nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *crlKey, PRBool isKRL);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,const SECItem *derName,
|
||||
PRBool isKRL);
|
||||
SECStatus
|
||||
nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl ,
|
||||
SECItem *derKey, char *url, PRBool isKRL);
|
||||
|
||||
NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB();
|
||||
NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *);
|
||||
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_NewTempCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert,
|
||||
char *nickname, PRBool isperm, PRBool copyDER);
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_DupCertificate(NSSLOWCERTCertificate *cert);
|
||||
void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert);
|
||||
void nsslowcert_DestroyTrust(NSSLOWCERTTrust *Trust);
|
||||
|
||||
/*
|
||||
* Lookup a certificate in the databases without locking
|
||||
* "certKey" is the database key to look for
|
||||
*
|
||||
* XXX - this should be internal, but pkcs 11 needs to call it during a
|
||||
* traversal.
|
||||
*/
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
|
||||
|
||||
/*
|
||||
* Lookup trust for a certificate in the databases without locking
|
||||
* "certKey" is the database key to look for
|
||||
*
|
||||
* XXX - this should be internal, but pkcs 11 needs to call it during a
|
||||
* traversal.
|
||||
*/
|
||||
NSSLOWCERTTrust *
|
||||
nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
|
||||
|
||||
/*
|
||||
** Generate a certificate key from the issuer and serialnumber, then look it
|
||||
** up in the database. Return the cert if found.
|
||||
** "issuerAndSN" is the issuer and serial number to look for
|
||||
*/
|
||||
extern NSSLOWCERTCertificate *
|
||||
nsslowcert_FindCertByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
|
||||
|
||||
/*
|
||||
** Generate a certificate key from the issuer and serialnumber, then look it
|
||||
** up in the database. Return the cert if found.
|
||||
** "issuerAndSN" is the issuer and serial number to look for
|
||||
*/
|
||||
extern NSSLOWCERTTrust *
|
||||
nsslowcert_FindTrustByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
|
||||
|
||||
/*
|
||||
** Find a certificate in the database by a DER encoded certificate
|
||||
** "derCert" is the DER encoded certificate
|
||||
*/
|
||||
extern NSSLOWCERTCertificate *
|
||||
nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
|
||||
|
||||
/* convert an email address to lower case */
|
||||
char *nsslowcert_FixupEmailAddr(char *emailAddr);
|
||||
|
||||
/*
|
||||
** Decode a DER encoded certificate into an NSSLOWCERTCertificate structure
|
||||
** "derSignedCert" is the DER encoded signed certificate
|
||||
** "copyDER" is true if the DER should be copied, false if the
|
||||
** existing copy should be referenced
|
||||
** "nickname" is the nickname to use in the database. If it is NULL
|
||||
** then a temporary nickname is generated.
|
||||
*/
|
||||
extern NSSLOWCERTCertificate *
|
||||
nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, char *nickname);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key);
|
||||
|
||||
certDBEntrySMime *
|
||||
nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle,
|
||||
char *emailAddr);
|
||||
void
|
||||
nsslowcert_DestroyDBEntry(certDBEntry *entry);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
|
||||
const char *domain, const char *prefix,
|
||||
NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile);
|
||||
|
||||
void
|
||||
nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle);
|
||||
|
||||
/*
|
||||
* is certa newer than certb? If one is expired, pick the other one.
|
||||
*/
|
||||
PRBool
|
||||
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb);
|
||||
|
||||
|
||||
SECStatus
|
||||
nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
|
||||
certDBEntryType type,
|
||||
SECStatus (* callback)(SECItem *data, SECItem *key,
|
||||
certDBEntryType type, void *pdata),
|
||||
void *udata );
|
||||
SECStatus
|
||||
nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *derSubject,
|
||||
NSSLOWCERTCertCallback cb, void *cbarg);
|
||||
int
|
||||
nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
|
||||
SECItem *derSubject);
|
||||
SECStatus
|
||||
nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
|
||||
char *nickname, NSSLOWCERTCertCallback cb, void *cbarg);
|
||||
|
||||
int
|
||||
nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
|
||||
char *nickname);
|
||||
SECStatus
|
||||
nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert,
|
||||
NSSLOWCERTCertTrust *trust);
|
||||
|
||||
SECStatus
|
||||
nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
|
||||
SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime);
|
||||
|
||||
/*
|
||||
* Change the trust attributes of a certificate and make them permanent
|
||||
* in the database.
|
||||
*/
|
||||
SECStatus
|
||||
nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle,
|
||||
NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust);
|
||||
|
||||
PRBool
|
||||
nsslowcert_needDBVerify(NSSLOWCERTCertDBHandle *handle);
|
||||
|
||||
void
|
||||
nsslowcert_setDBVerify(NSSLOWCERTCertDBHandle *handle, PRBool value);
|
||||
|
||||
PRBool
|
||||
nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust);
|
||||
|
||||
void
|
||||
nsslowcert_DestroyFreeLists(void);
|
||||
|
||||
void
|
||||
nsslowcert_DestroyGlobalLocks(void);
|
||||
|
||||
void
|
||||
pkcs11_freeNickname(char *nickname, char *space);
|
||||
|
||||
char *
|
||||
pkcs11_copyNickname(char *nickname, char *space, int spaceLen);
|
||||
|
||||
void
|
||||
pkcs11_freeStaticData(unsigned char *data, unsigned char *space);
|
||||
|
||||
unsigned char *
|
||||
pkcs11_allocStaticData(int datalen, unsigned char *space, int spaceLen);
|
||||
|
||||
unsigned char *
|
||||
pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space,
|
||||
int spaceLen);
|
||||
NSSLOWCERTCertificate *
|
||||
nsslowcert_CreateCert(void);
|
||||
|
||||
certDBEntry *
|
||||
nsslowcert_DecodeAnyDBEntry(SECItem *dbData, const SECItem *dbKey,
|
||||
certDBEntryType entryType, void *pdata);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _PCERTDB_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,450 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* certt.h - public data structures for the certificate library
|
||||
*
|
||||
* $Id: pcertt.h,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#ifndef _PCERTT_H_
|
||||
#define _PCERTT_H_
|
||||
|
||||
#include "prclist.h"
|
||||
#include "pkcs11t.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "plarena.h"
|
||||
#include "prcvar.h"
|
||||
#include "nssilock.h"
|
||||
#include "prio.h"
|
||||
#include "prmon.h"
|
||||
|
||||
/* Non-opaque objects */
|
||||
typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle;
|
||||
typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey;
|
||||
|
||||
typedef struct NSSLOWCERTTrustStr NSSLOWCERTTrust;
|
||||
typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust;
|
||||
typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate;
|
||||
typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList;
|
||||
typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN;
|
||||
typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData;
|
||||
typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo;
|
||||
typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity;
|
||||
|
||||
/*
|
||||
** An X.509 validity object
|
||||
*/
|
||||
struct NSSLOWCERTValidityStr {
|
||||
PRArenaPool *arena;
|
||||
SECItem notBefore;
|
||||
SECItem notAfter;
|
||||
};
|
||||
|
||||
/*
|
||||
* A serial number and issuer name, which is used as a database key
|
||||
*/
|
||||
struct NSSLOWCERTCertKeyStr {
|
||||
SECItem serialNumber;
|
||||
SECItem derIssuer;
|
||||
};
|
||||
|
||||
/*
|
||||
** A signed data object. Used to implement the "signed" macro used
|
||||
** in the X.500 specs.
|
||||
*/
|
||||
struct NSSLOWCERTSignedDataStr {
|
||||
SECItem data;
|
||||
SECAlgorithmID signatureAlgorithm;
|
||||
SECItem signature;
|
||||
};
|
||||
|
||||
/*
|
||||
** An X.509 subject-public-key-info object
|
||||
*/
|
||||
struct NSSLOWCERTSubjectPublicKeyInfoStr {
|
||||
PRArenaPool *arena;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem subjectPublicKey;
|
||||
};
|
||||
|
||||
typedef struct _certDBEntryCert certDBEntryCert;
|
||||
typedef struct _certDBEntryRevocation certDBEntryRevocation;
|
||||
|
||||
struct NSSLOWCERTCertTrustStr {
|
||||
unsigned int sslFlags;
|
||||
unsigned int emailFlags;
|
||||
unsigned int objectSigningFlags;
|
||||
};
|
||||
|
||||
/*
|
||||
** PKCS11 Trust representation
|
||||
*/
|
||||
struct NSSLOWCERTTrustStr {
|
||||
NSSLOWCERTTrust *next;
|
||||
NSSLOWCERTCertDBHandle *dbhandle;
|
||||
SECItem dbKey; /* database key for this cert */
|
||||
certDBEntryCert *dbEntry; /* database entry struct */
|
||||
NSSLOWCERTCertTrust *trust;
|
||||
SECItem *derCert; /* original DER for the cert */
|
||||
unsigned char dbKeySpace[512];
|
||||
};
|
||||
|
||||
/*
|
||||
** An X.509 certificate object (the unsigned form)
|
||||
*/
|
||||
struct NSSLOWCERTCertificateStr {
|
||||
/* the arena is used to allocate any data structures that have the same
|
||||
* lifetime as the cert. This is all stuff that hangs off of the cert
|
||||
* structure, and is all freed at the same time. I is used when the
|
||||
* cert is decoded, destroyed, and at some times when it changes
|
||||
* state
|
||||
*/
|
||||
NSSLOWCERTCertificate *next;
|
||||
NSSLOWCERTCertDBHandle *dbhandle;
|
||||
|
||||
SECItem derCert; /* original DER for the cert */
|
||||
SECItem derIssuer; /* DER for issuer name */
|
||||
SECItem derSN;
|
||||
SECItem serialNumber;
|
||||
SECItem derSubject; /* DER for subject name */
|
||||
SECItem derSubjKeyInfo;
|
||||
NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
|
||||
SECItem certKey; /* database key for this cert */
|
||||
SECItem validity;
|
||||
certDBEntryCert *dbEntry; /* database entry struct */
|
||||
SECItem subjectKeyID; /* x509v3 subject key identifier */
|
||||
SECItem extensions;
|
||||
char *nickname;
|
||||
char *emailAddr;
|
||||
NSSLOWCERTCertTrust *trust;
|
||||
|
||||
/* the reference count is modified whenever someone looks up, dups
|
||||
* or destroys a certificate
|
||||
*/
|
||||
int referenceCount;
|
||||
|
||||
char nicknameSpace[200];
|
||||
char emailAddrSpace[200];
|
||||
unsigned char certKeySpace[512];
|
||||
};
|
||||
|
||||
#define SEC_CERTIFICATE_VERSION_1 0 /* default created */
|
||||
#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */
|
||||
#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */
|
||||
|
||||
#define SEC_CRL_VERSION_1 0 /* default */
|
||||
#define SEC_CRL_VERSION_2 1 /* v2 extensions */
|
||||
|
||||
struct NSSLOWCERTIssuerAndSNStr {
|
||||
SECItem derIssuer;
|
||||
SECItem serialNumber;
|
||||
};
|
||||
|
||||
typedef SECStatus (* NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg);
|
||||
|
||||
/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */
|
||||
/* callback to return database name based on version number */
|
||||
typedef char * (*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion);
|
||||
|
||||
/* XXX Lisa thinks the template declarations belong in cert.h, not here? */
|
||||
|
||||
#include "secasn1t.h" /* way down here because I expect template stuff to
|
||||
* move out of here anyway */
|
||||
|
||||
/*
|
||||
* Certificate Database related definitions and data structures
|
||||
*/
|
||||
|
||||
/* version number of certificate database */
|
||||
#define CERT_DB_FILE_VERSION 8
|
||||
#define CERT_DB_V7_FILE_VERSION 7
|
||||
#define CERT_DB_CONTENT_VERSION 2
|
||||
|
||||
#define SEC_DB_ENTRY_HEADER_LEN 3
|
||||
#define SEC_DB_KEY_HEADER_LEN 1
|
||||
|
||||
/* All database entries have this form:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 version
|
||||
* 1 type
|
||||
* 2 flags
|
||||
*/
|
||||
|
||||
/* database entry types */
|
||||
typedef enum {
|
||||
certDBEntryTypeVersion = 0,
|
||||
certDBEntryTypeCert = 1,
|
||||
certDBEntryTypeNickname = 2,
|
||||
certDBEntryTypeSubject = 3,
|
||||
certDBEntryTypeRevocation = 4,
|
||||
certDBEntryTypeKeyRevocation = 5,
|
||||
certDBEntryTypeSMimeProfile = 6,
|
||||
certDBEntryTypeContentVersion = 7,
|
||||
certDBEntryTypeBlob = 8
|
||||
} certDBEntryType;
|
||||
|
||||
typedef struct {
|
||||
certDBEntryType type;
|
||||
unsigned int version;
|
||||
unsigned int flags;
|
||||
PRArenaPool *arena;
|
||||
} certDBEntryCommon;
|
||||
|
||||
/*
|
||||
* Certificate entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 sslFlags-msb
|
||||
* 1 sslFlags-lsb
|
||||
* 2 emailFlags-msb
|
||||
* 3 emailFlags-lsb
|
||||
* 4 objectSigningFlags-msb
|
||||
* 5 objectSigningFlags-lsb
|
||||
* 6 derCert-len-msb
|
||||
* 7 derCert-len-lsb
|
||||
* 8 nickname-len-msb
|
||||
* 9 nickname-len-lsb
|
||||
* ... derCert
|
||||
* ... nickname
|
||||
*
|
||||
* NOTE: the nickname string as stored in the database is null terminated,
|
||||
* in other words, the last byte of the db entry is always 0
|
||||
* if a nickname is present.
|
||||
* NOTE: if nickname is not present, then nickname-len-msb and
|
||||
* nickname-len-lsb will both be zero.
|
||||
*/
|
||||
struct _certDBEntryCert {
|
||||
certDBEntryCommon common;
|
||||
certDBEntryCert *next;
|
||||
NSSLOWCERTCertTrust trust;
|
||||
SECItem derCert;
|
||||
char *nickname;
|
||||
char nicknameSpace[200];
|
||||
unsigned char derCertSpace[2048];
|
||||
};
|
||||
|
||||
/*
|
||||
* Certificate Nickname entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 subjectname-len-msb
|
||||
* 1 subjectname-len-lsb
|
||||
* 2... subjectname
|
||||
*
|
||||
* The database key for this type of entry is a nickname string
|
||||
* The "subjectname" value is the DER encoded DN of the identity
|
||||
* that matches this nickname.
|
||||
*/
|
||||
typedef struct {
|
||||
certDBEntryCommon common;
|
||||
char *nickname;
|
||||
SECItem subjectName;
|
||||
} certDBEntryNickname;
|
||||
|
||||
#define DB_NICKNAME_ENTRY_HEADER_LEN 2
|
||||
|
||||
/*
|
||||
* Certificate Subject entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 ncerts-msb
|
||||
* 1 ncerts-lsb
|
||||
* 2 nickname-msb
|
||||
* 3 nickname-lsb
|
||||
* 4 emailAddr-msb
|
||||
* 5 emailAddr-lsb
|
||||
* ... nickname
|
||||
* ... emailAddr
|
||||
* ...+2*i certkey-len-msb
|
||||
* ...+1+2*i certkey-len-lsb
|
||||
* ...+2*ncerts+2*i keyid-len-msb
|
||||
* ...+1+2*ncerts+2*i keyid-len-lsb
|
||||
* ... certkeys
|
||||
* ... keyids
|
||||
*
|
||||
* The database key for this type of entry is the DER encoded subject name
|
||||
* The "certkey" value is an array of certificate database lookup keys that
|
||||
* points to the database entries for the certificates that matche
|
||||
* this subject.
|
||||
*
|
||||
*/
|
||||
typedef struct _certDBEntrySubject {
|
||||
certDBEntryCommon common;
|
||||
SECItem derSubject;
|
||||
unsigned int ncerts;
|
||||
char *nickname;
|
||||
SECItem *certKeys;
|
||||
SECItem *keyIDs;
|
||||
char **emailAddrs;
|
||||
unsigned int nemailAddrs;
|
||||
} certDBEntrySubject;
|
||||
|
||||
#define DB_SUBJECT_ENTRY_HEADER_LEN 6
|
||||
|
||||
/*
|
||||
* Certificate SMIME profile entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 subjectname-len-msb
|
||||
* 1 subjectname-len-lsb
|
||||
* 2 smimeoptions-len-msb
|
||||
* 3 smimeoptions-len-lsb
|
||||
* 4 options-date-len-msb
|
||||
* 5 options-date-len-lsb
|
||||
* 6... subjectname
|
||||
* ... smimeoptions
|
||||
* ... options-date
|
||||
*
|
||||
* The database key for this type of entry is the email address string
|
||||
* The "subjectname" value is the DER encoded DN of the identity
|
||||
* that matches this nickname.
|
||||
* The "smimeoptions" value is a string that represents the algorithm
|
||||
* capabilities on the remote user.
|
||||
* The "options-date" is the date that the smime options value was created.
|
||||
* This is generally the signing time of the signed message that contained
|
||||
* the options. It is a UTCTime value.
|
||||
*/
|
||||
typedef struct {
|
||||
certDBEntryCommon common;
|
||||
char *emailAddr;
|
||||
SECItem subjectName;
|
||||
SECItem smimeOptions;
|
||||
SECItem optionsDate;
|
||||
} certDBEntrySMime;
|
||||
|
||||
#define DB_SMIME_ENTRY_HEADER_LEN 6
|
||||
|
||||
/*
|
||||
* Crl/krl entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 derCert-len-msb
|
||||
* 1 derCert-len-lsb
|
||||
* 2 url-len-msb
|
||||
* 3 url-len-lsb
|
||||
* ... derCert
|
||||
* ... url
|
||||
*
|
||||
* NOTE: the url string as stored in the database is null terminated,
|
||||
* in other words, the last byte of the db entry is always 0
|
||||
* if a nickname is present.
|
||||
* NOTE: if url is not present, then url-len-msb and
|
||||
* url-len-lsb will both be zero.
|
||||
*/
|
||||
#define DB_CRL_ENTRY_HEADER_LEN 4
|
||||
struct _certDBEntryRevocation {
|
||||
certDBEntryCommon common;
|
||||
SECItem derCrl;
|
||||
char *url; /* where to load the crl from */
|
||||
};
|
||||
|
||||
/*
|
||||
* Database Version Entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* only the low level header...
|
||||
*
|
||||
* The database key for this type of entry is the string "Version"
|
||||
*/
|
||||
typedef struct {
|
||||
certDBEntryCommon common;
|
||||
} certDBEntryVersion;
|
||||
|
||||
#define SEC_DB_VERSION_KEY "Version"
|
||||
#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY)
|
||||
|
||||
/*
|
||||
* Database Content Version Entry:
|
||||
*
|
||||
* byte offset field
|
||||
* ----------- -----
|
||||
* 0 contentVersion
|
||||
*
|
||||
* The database key for this type of entry is the string "ContentVersion"
|
||||
*/
|
||||
typedef struct {
|
||||
certDBEntryCommon common;
|
||||
char contentVersion;
|
||||
} certDBEntryContentVersion;
|
||||
|
||||
#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion"
|
||||
#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY)
|
||||
|
||||
typedef union {
|
||||
certDBEntryCommon common;
|
||||
certDBEntryCert cert;
|
||||
certDBEntryContentVersion content;
|
||||
certDBEntryNickname nickname;
|
||||
certDBEntryRevocation revocation;
|
||||
certDBEntrySMime smime;
|
||||
certDBEntrySubject subject;
|
||||
certDBEntryVersion version;
|
||||
} certDBEntry;
|
||||
|
||||
/* length of the fixed part of a database entry */
|
||||
#define DBCERT_V4_HEADER_LEN 7
|
||||
#define DB_CERT_V5_ENTRY_HEADER_LEN 7
|
||||
#define DB_CERT_V6_ENTRY_HEADER_LEN 7
|
||||
#define DB_CERT_ENTRY_HEADER_LEN 10
|
||||
|
||||
/* common flags for all types of certificates */
|
||||
#define CERTDB_VALID_PEER (1<<0)
|
||||
#define CERTDB_TRUSTED (1<<1)
|
||||
#define CERTDB_SEND_WARN (1<<2)
|
||||
#define CERTDB_VALID_CA (1<<3)
|
||||
#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */
|
||||
#define CERTDB_NS_TRUSTED_CA (1<<5)
|
||||
#define CERTDB_USER (1<<6)
|
||||
#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */
|
||||
#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */
|
||||
#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */
|
||||
#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */
|
||||
#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */
|
||||
|
||||
/* bits not affected by the CKO_NETSCAPE_TRUST object */
|
||||
#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \
|
||||
CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \
|
||||
CERTDB_GOVT_APPROVED_CA)
|
||||
|
||||
#endif /* _PCERTT_H_ */
|
||||
@@ -1,773 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* The following code handles the storage of PKCS 11 modules used by the
|
||||
* NSS. This file is written to abstract away how the modules are
|
||||
* stored so we can deside that later.
|
||||
*/
|
||||
|
||||
#include "pk11pars.h"
|
||||
#include "lgdb.h"
|
||||
#include "mcom_db.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
|
||||
|
||||
/* Construct a database key for a given module */
|
||||
static SECStatus secmod_MakeKey(DBT *key, char * module) {
|
||||
int len = 0;
|
||||
char *commonName;
|
||||
|
||||
commonName = secmod_argGetParamValue("name",module);
|
||||
if (commonName == NULL) {
|
||||
commonName = secmod_argGetParamValue("library",module);
|
||||
}
|
||||
if (commonName == NULL) return SECFailure;
|
||||
len = PORT_Strlen(commonName);
|
||||
key->data = commonName;
|
||||
key->size = len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* free out constructed database key */
|
||||
static void
|
||||
secmod_FreeKey(DBT *key)
|
||||
{
|
||||
if (key->data) {
|
||||
PORT_Free(key->data);
|
||||
}
|
||||
key->data = NULL;
|
||||
key->size = 0;
|
||||
}
|
||||
|
||||
typedef struct secmodDataStr secmodData;
|
||||
typedef struct secmodSlotDataStr secmodSlotData;
|
||||
struct secmodDataStr {
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned char nameStart[2];
|
||||
unsigned char slotOffset[2];
|
||||
unsigned char internal;
|
||||
unsigned char fips;
|
||||
unsigned char ssl[8];
|
||||
unsigned char trustOrder[4];
|
||||
unsigned char cipherOrder[4];
|
||||
unsigned char reserved1;
|
||||
unsigned char isModuleDB;
|
||||
unsigned char isModuleDBOnly;
|
||||
unsigned char isCritical;
|
||||
unsigned char reserved[4];
|
||||
unsigned char names[6]; /* enough space for the length fields */
|
||||
};
|
||||
|
||||
struct secmodSlotDataStr {
|
||||
unsigned char slotID[4];
|
||||
unsigned char defaultFlags[4];
|
||||
unsigned char timeout[4];
|
||||
unsigned char askpw;
|
||||
unsigned char hasRootCerts;
|
||||
unsigned char reserved[18]; /* this makes it a round 32 bytes */
|
||||
};
|
||||
|
||||
#define SECMOD_DB_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_VERSION_MINOR 6
|
||||
#define SECMOD_DB_EXT1_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_EXT1_VERSION_MINOR 6
|
||||
#define SECMOD_DB_NOUI_VERSION_MAJOR 0
|
||||
#define SECMOD_DB_NOUI_VERSION_MINOR 4
|
||||
|
||||
#define SECMOD_PUTSHORT(dest,src) \
|
||||
(dest)[1] = (unsigned char) ((src)&0xff); \
|
||||
(dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
|
||||
#define SECMOD_PUTLONG(dest,src) \
|
||||
(dest)[3] = (unsigned char) ((src)&0xff); \
|
||||
(dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
|
||||
(dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
|
||||
(dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
|
||||
#define SECMOD_GETSHORT(src) \
|
||||
((unsigned short) (((src)[0] << 8) | (src)[1]))
|
||||
#define SECMOD_GETLONG(src) \
|
||||
((unsigned long) (( (unsigned long) (src)[0] << 24) | \
|
||||
( (unsigned long) (src)[1] << 16) | \
|
||||
( (unsigned long) (src)[2] << 8) | \
|
||||
(unsigned long) (src)[3]))
|
||||
|
||||
/*
|
||||
* build a data base entry from a module
|
||||
*/
|
||||
static SECStatus
|
||||
secmod_EncodeData(DBT *data, char * module)
|
||||
{
|
||||
secmodData *encoded = NULL;
|
||||
secmodSlotData *slot;
|
||||
unsigned char *dataPtr;
|
||||
unsigned short len, len2 = 0, len3 = 0;
|
||||
int count = 0;
|
||||
unsigned short offset;
|
||||
int dataLen, i;
|
||||
unsigned long order;
|
||||
unsigned long ssl[2];
|
||||
char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
|
||||
char *slotParams, *ciphers;
|
||||
PK11PreSlotInfo *slotInfo = NULL;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
rv = secmod_argParseModuleSpec(module,&dllName,&commonName,¶m,&nss);
|
||||
if (rv != SECSuccess) return rv;
|
||||
rv = SECFailure;
|
||||
|
||||
if (commonName == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
len = PORT_Strlen(commonName);
|
||||
if (dllName) {
|
||||
len2 = PORT_Strlen(dllName);
|
||||
}
|
||||
if (param) {
|
||||
len3 = PORT_Strlen(param);
|
||||
}
|
||||
|
||||
slotParams = secmod_argGetParamValue("slotParams",nss);
|
||||
slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
|
||||
if (slotParams) PORT_Free(slotParams);
|
||||
|
||||
if (count && slotInfo == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
|
||||
count*sizeof(secmodSlotData);
|
||||
|
||||
data->data = (unsigned char *) PORT_ZAlloc(dataLen);
|
||||
encoded = (secmodData *)data->data;
|
||||
dataPtr = (unsigned char *) data->data;
|
||||
data->size = dataLen;
|
||||
|
||||
if (encoded == NULL) {
|
||||
/* set error */
|
||||
goto loser;
|
||||
}
|
||||
|
||||
encoded->major = SECMOD_DB_VERSION_MAJOR;
|
||||
encoded->minor = SECMOD_DB_VERSION_MINOR;
|
||||
encoded->internal = (unsigned char)
|
||||
(secmod_argHasFlag("flags","internal",nss) ? 1 : 0);
|
||||
encoded->fips = (unsigned char)
|
||||
(secmod_argHasFlag("flags","FIPS",nss) ? 1 : 0);
|
||||
encoded->isModuleDB = (unsigned char)
|
||||
(secmod_argHasFlag("flags","isModuleDB",nss) ? 1 : 0);
|
||||
encoded->isModuleDBOnly = (unsigned char)
|
||||
(secmod_argHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
|
||||
encoded->isCritical = (unsigned char)
|
||||
(secmod_argHasFlag("flags","critical",nss) ? 1 : 0);
|
||||
|
||||
order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER,
|
||||
NULL);
|
||||
SECMOD_PUTLONG(encoded->trustOrder,order);
|
||||
order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER,
|
||||
NULL);
|
||||
SECMOD_PUTLONG(encoded->cipherOrder,order);
|
||||
|
||||
|
||||
ciphers = secmod_argGetParamValue("ciphers",nss);
|
||||
secmod_argSetNewCipherFlags(&ssl[0], ciphers);
|
||||
SECMOD_PUTLONG(encoded->ssl,ssl[0]);
|
||||
SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]);
|
||||
if (ciphers) PORT_Free(ciphers);
|
||||
|
||||
offset = (unsigned short) &(((secmodData *)0)->names[0]);
|
||||
SECMOD_PUTSHORT(encoded->nameStart,offset);
|
||||
offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
|
||||
SECMOD_PUTSHORT(encoded->slotOffset,offset);
|
||||
|
||||
|
||||
SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
|
||||
slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
|
||||
|
||||
offset = 0;
|
||||
SECMOD_PUTSHORT(encoded->names,len);
|
||||
offset += sizeof(unsigned short);
|
||||
PORT_Memcpy(&encoded->names[offset],commonName,len);
|
||||
offset += len;
|
||||
|
||||
|
||||
SECMOD_PUTSHORT(&encoded->names[offset],len2);
|
||||
offset += sizeof(unsigned short);
|
||||
if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
|
||||
offset += len2;
|
||||
|
||||
SECMOD_PUTSHORT(&encoded->names[offset],len3);
|
||||
offset += sizeof(unsigned short);
|
||||
if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
|
||||
offset += len3;
|
||||
|
||||
if (count) {
|
||||
for (i=0; i < count; i++) {
|
||||
SECMOD_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
|
||||
SECMOD_PUTLONG(slot[i].defaultFlags,
|
||||
slotInfo[i].defaultFlags);
|
||||
SECMOD_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
|
||||
slot[i].askpw = slotInfo[i].askpw;
|
||||
slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
|
||||
PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
|
||||
}
|
||||
}
|
||||
rv = SECSuccess;
|
||||
|
||||
loser:
|
||||
if (commonName) PORT_Free(commonName);
|
||||
if (dllName) PORT_Free(dllName);
|
||||
if (param) PORT_Free(param);
|
||||
if (slotInfo) PORT_Free(slotInfo);
|
||||
if (nss) PORT_Free(nss);
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_FreeData(DBT *data)
|
||||
{
|
||||
if (data->data) {
|
||||
PORT_Free(data->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_FreeSlotStrings(char **slotStrings, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
if (slotStrings[i]) {
|
||||
PR_smprintf_free(slotStrings[i]);
|
||||
slotStrings[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* build a module from the data base entry.
|
||||
*/
|
||||
static char *
|
||||
secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
|
||||
{
|
||||
secmodData *encoded;
|
||||
secmodSlotData *slots;
|
||||
PLArenaPool *arena;
|
||||
char *commonName = NULL;
|
||||
char *dllName = NULL;
|
||||
char *parameters = NULL;
|
||||
char *nss;
|
||||
char *moduleSpec;
|
||||
char **slotStrings = NULL;
|
||||
unsigned char *names;
|
||||
unsigned long slotCount;
|
||||
unsigned long ssl0 =0;
|
||||
unsigned long ssl1 =0;
|
||||
unsigned long slotID;
|
||||
unsigned long defaultFlags;
|
||||
unsigned long timeout;
|
||||
unsigned long trustOrder =SECMOD_DEFAULT_TRUST_ORDER;
|
||||
unsigned long cipherOrder =SECMOD_DEFAULT_CIPHER_ORDER;
|
||||
unsigned short len;
|
||||
unsigned short namesOffset = 0; /* start of the names block */
|
||||
unsigned long namesRunningOffset; /* offset to name we are
|
||||
* currently processing */
|
||||
unsigned short slotOffset;
|
||||
PRBool isOldVersion = PR_FALSE;
|
||||
PRBool internal;
|
||||
PRBool isFIPS;
|
||||
PRBool isModuleDB =PR_FALSE;
|
||||
PRBool isModuleDBOnly =PR_FALSE;
|
||||
PRBool extended =PR_FALSE;
|
||||
int i;
|
||||
|
||||
|
||||
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
|
||||
if (arena == NULL)
|
||||
return NULL;
|
||||
|
||||
#define CHECK_SIZE(x) \
|
||||
if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
** Process the buffer header, which is the secmodData struct.
|
||||
** It may be an old or new version. Check the length for each.
|
||||
*/
|
||||
|
||||
CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
|
||||
|
||||
encoded = (secmodData *)data->data;
|
||||
|
||||
internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
|
||||
isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
|
||||
|
||||
if (retInternal)
|
||||
*retInternal = internal;
|
||||
if (internal) {
|
||||
parameters = PORT_ArenaStrdup(arena,defParams);
|
||||
if (parameters == NULL)
|
||||
goto loser;
|
||||
}
|
||||
if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
|
||||
(encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
|
||||
isOldVersion = PR_TRUE;
|
||||
}
|
||||
if ((encoded->major == SECMOD_DB_EXT1_VERSION_MAJOR) &&
|
||||
(encoded->minor >= SECMOD_DB_EXT1_VERSION_MINOR)) {
|
||||
CHECK_SIZE( sizeof(secmodData));
|
||||
trustOrder = SECMOD_GETLONG(encoded->trustOrder);
|
||||
cipherOrder = SECMOD_GETLONG(encoded->cipherOrder);
|
||||
isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
|
||||
isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
|
||||
extended = PR_TRUE;
|
||||
}
|
||||
if (internal && !extended) {
|
||||
trustOrder = 0;
|
||||
cipherOrder = 100;
|
||||
}
|
||||
/* decode SSL cipher enable flags */
|
||||
ssl0 = SECMOD_GETLONG(encoded->ssl);
|
||||
ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
|
||||
|
||||
slotOffset = SECMOD_GETSHORT(encoded->slotOffset);
|
||||
namesOffset = SECMOD_GETSHORT(encoded->nameStart);
|
||||
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
** Now process the variable length set of names.
|
||||
** The names have this structure:
|
||||
** struct {
|
||||
** BYTE commonNameLen[ 2 ];
|
||||
** BYTE commonName [ commonNameLen ];
|
||||
** BTTE libNameLen [ 2 ];
|
||||
** BYTE libName [ libNameLen ];
|
||||
** If it is "extended" it also has these members:
|
||||
** BYTE initStringLen[ 2 ];
|
||||
** BYTE initString [ initStringLen ];
|
||||
** }
|
||||
*/
|
||||
|
||||
namesRunningOffset = namesOffset;
|
||||
/* copy the module's common name */
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
names = (unsigned char *)data->data;
|
||||
len = SECMOD_GETSHORT(names+namesRunningOffset);
|
||||
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len);
|
||||
commonName = (char*)PORT_ArenaAlloc(arena,len+1);
|
||||
if (commonName == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
|
||||
commonName[len] = 0;
|
||||
namesRunningOffset += len + 2;
|
||||
|
||||
/* copy the module's shared library file name. */
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
len = SECMOD_GETSHORT(names + namesRunningOffset);
|
||||
if (len) {
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len);
|
||||
dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
|
||||
if (dllName == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
|
||||
dllName[len] = 0;
|
||||
}
|
||||
namesRunningOffset += len + 2;
|
||||
|
||||
/* copy the module's initialization string, if present. */
|
||||
if (!internal && extended) {
|
||||
CHECK_SIZE( namesRunningOffset + 2);
|
||||
len = SECMOD_GETSHORT(names+namesRunningOffset);
|
||||
if (len) {
|
||||
CHECK_SIZE( namesRunningOffset + 2 + len );
|
||||
parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
|
||||
if (parameters == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
|
||||
parameters[len] = 0;
|
||||
}
|
||||
namesRunningOffset += len + 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consistency check: Make sure the slot and names blocks don't
|
||||
* overlap. These blocks can occur in any order, so this check is made
|
||||
* in 2 parts. First we check the case where the slot block starts
|
||||
* after the name block. Later, when we have the slot block length,
|
||||
* we check the case where slot block starts before the name block.
|
||||
* NOTE: in most cases any overlap will likely be detected by invalid
|
||||
* data read from the blocks, but it's better to find out sooner
|
||||
* than later.
|
||||
*/
|
||||
if (slotOffset >= namesOffset) { /* slot block starts after name block */
|
||||
if (slotOffset < namesRunningOffset) {
|
||||
goto db_loser;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
** Part 3, process the slot table.
|
||||
** This part has this structure:
|
||||
** struct {
|
||||
** BYTE slotCount [ 2 ];
|
||||
** secmodSlotData [ slotCount ];
|
||||
** {
|
||||
*/
|
||||
|
||||
CHECK_SIZE( slotOffset + 2 );
|
||||
slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
|
||||
|
||||
/*
|
||||
* Consistency check: Part 2. We now have the slot block length, we can
|
||||
* check the case where the slotblock procedes the name block.
|
||||
*/
|
||||
if (slotOffset < namesOffset) { /* slot block starts before name block */
|
||||
if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
|
||||
goto db_loser;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
|
||||
slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
|
||||
|
||||
/* slotCount; */
|
||||
slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
|
||||
if (slotStrings == NULL)
|
||||
goto loser;
|
||||
for (i=0; i < (int) slotCount; i++, slots++) {
|
||||
PRBool hasRootCerts =PR_FALSE;
|
||||
PRBool hasRootTrust =PR_FALSE;
|
||||
slotID = SECMOD_GETLONG(slots->slotID);
|
||||
defaultFlags = SECMOD_GETLONG(slots->defaultFlags);
|
||||
timeout = SECMOD_GETLONG(slots->timeout);
|
||||
hasRootCerts = slots->hasRootCerts;
|
||||
if (isOldVersion && internal && (slotID != 2)) {
|
||||
unsigned long internalFlags=
|
||||
secmod_argSlotFlags("slotFlags",SECMOD_SLOT_FLAGS);
|
||||
defaultFlags |= internalFlags;
|
||||
}
|
||||
if (hasRootCerts && !extended) {
|
||||
trustOrder = 100;
|
||||
}
|
||||
|
||||
slotStrings[i] = secmod_mkSlotString(slotID, defaultFlags, timeout,
|
||||
(unsigned char)slots->askpw,
|
||||
hasRootCerts, hasRootTrust);
|
||||
if (slotStrings[i] == NULL) {
|
||||
secmod_FreeSlotStrings(slotStrings,i);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB,
|
||||
isModuleDBOnly, internal, trustOrder, cipherOrder,
|
||||
ssl0, ssl1);
|
||||
secmod_FreeSlotStrings(slotStrings,slotCount);
|
||||
/* it's permissible (and normal) for nss to be NULL. it simply means
|
||||
* there are no NSS specific parameters in the database */
|
||||
moduleSpec = secmod_mkNewModuleSpec(dllName,commonName,parameters,nss);
|
||||
PR_smprintf_free(nss);
|
||||
PORT_FreeArena(arena,PR_TRUE);
|
||||
return moduleSpec;
|
||||
|
||||
db_loser:
|
||||
PORT_SetError(SEC_ERROR_BAD_DATABASE);
|
||||
loser:
|
||||
PORT_FreeArena(arena,PR_TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DB *
|
||||
secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
|
||||
PRBool readOnly, PRBool update)
|
||||
{
|
||||
DB *pkcs11db = NULL;
|
||||
|
||||
|
||||
if (appName) {
|
||||
char *secname = PORT_Strdup(filename);
|
||||
int len = strlen(secname);
|
||||
int status = RDB_FAIL;
|
||||
|
||||
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
|
||||
secname[len-3] = 0;
|
||||
}
|
||||
pkcs11db=
|
||||
rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
if (update && !pkcs11db) {
|
||||
DB *updatedb;
|
||||
|
||||
pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
|
||||
if (!pkcs11db) {
|
||||
if (status == RDB_RETRY) {
|
||||
pkcs11db= rdbopen(appName, "", secname,
|
||||
readOnly ? NO_RDONLY:NO_RDWR, NULL);
|
||||
}
|
||||
PORT_Free(secname);
|
||||
return pkcs11db;
|
||||
}
|
||||
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
|
||||
if (updatedb) {
|
||||
db_Copy(pkcs11db,updatedb);
|
||||
(*updatedb->close)(updatedb);
|
||||
} else {
|
||||
(*pkcs11db->close)(pkcs11db);
|
||||
PORT_Free(secname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
PORT_Free(secname);
|
||||
return pkcs11db;
|
||||
}
|
||||
|
||||
/* I'm sure we should do more checks here sometime... */
|
||||
pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
|
||||
|
||||
/* didn't exist? create it */
|
||||
if (pkcs11db == NULL) {
|
||||
if (readOnly)
|
||||
return NULL;
|
||||
|
||||
pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
|
||||
if (pkcs11db)
|
||||
(* pkcs11db->sync)(pkcs11db, 0);
|
||||
}
|
||||
return pkcs11db;
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_CloseDB(DB *pkcs11db)
|
||||
{
|
||||
(*pkcs11db->close)(pkcs11db);
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_addEscape(const char *string, char quote)
|
||||
{
|
||||
char *newString = 0;
|
||||
int escapes = 0, size = 0;
|
||||
const char *src;
|
||||
char *dest;
|
||||
|
||||
for (src=string; *src ; src++) {
|
||||
if ((*src == quote) || (*src == '\\')) escapes++;
|
||||
size++;
|
||||
}
|
||||
|
||||
newString = PORT_ZAlloc(escapes+size+1);
|
||||
if (newString == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (src=string, dest=newString; *src; src++,dest++) {
|
||||
if ((*src == '\\') || (*src == quote)) {
|
||||
*dest++ = '\\';
|
||||
}
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *module, PRBool rw);
|
||||
|
||||
#define SECMOD_STEP 10
|
||||
#define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
|
||||
/*
|
||||
* Read all the existing modules in
|
||||
*/
|
||||
char **
|
||||
legacy_ReadSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *params, PRBool rw)
|
||||
{
|
||||
DBT key,data;
|
||||
int ret;
|
||||
DB *pkcs11db = NULL;
|
||||
char **moduleList = NULL, **newModuleList = NULL;
|
||||
int moduleCount = 1;
|
||||
int useCount = SECMOD_STEP;
|
||||
|
||||
moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
|
||||
if (moduleList == NULL) return NULL;
|
||||
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
|
||||
if (pkcs11db == NULL) goto done;
|
||||
|
||||
/* read and parse the file or data base */
|
||||
ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
|
||||
if (ret) goto done;
|
||||
|
||||
|
||||
do {
|
||||
char *moduleString;
|
||||
PRBool internal = PR_FALSE;
|
||||
if ((moduleCount+1) >= useCount) {
|
||||
useCount += SECMOD_STEP;
|
||||
newModuleList =
|
||||
(char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
|
||||
if (newModuleList == NULL) goto done;
|
||||
moduleList = newModuleList;
|
||||
PORT_Memset(&moduleList[moduleCount+1],0,
|
||||
sizeof(char *)*SECMOD_STEP);
|
||||
}
|
||||
moduleString = secmod_DecodeData(params,&data,&internal);
|
||||
if (internal) {
|
||||
moduleList[0] = moduleString;
|
||||
} else {
|
||||
moduleList[moduleCount] = moduleString;
|
||||
moduleCount++;
|
||||
}
|
||||
} while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
|
||||
|
||||
done:
|
||||
if (!moduleList[0]) {
|
||||
char * newparams = secmod_addEscape(params,'"');
|
||||
if (newparams) {
|
||||
moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
|
||||
SECMOD_SLOT_FLAGS);
|
||||
PORT_Free(newparams);
|
||||
}
|
||||
}
|
||||
/* deal with trust cert db here */
|
||||
|
||||
if (pkcs11db) {
|
||||
secmod_CloseDB(pkcs11db);
|
||||
} else if (moduleList[0] && rw) {
|
||||
legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
|
||||
}
|
||||
if (!moduleList[0]) {
|
||||
PORT_Free(moduleList);
|
||||
moduleList = NULL;
|
||||
}
|
||||
return moduleList;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
|
||||
const char *dbname, char **moduleSpecList, PRBool rw)
|
||||
{
|
||||
if (moduleSpecList) {
|
||||
char **index;
|
||||
for(index = moduleSpecList; *index; index++) {
|
||||
PR_smprintf_free(*index);
|
||||
}
|
||||
PORT_Free(moduleSpecList);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a module from the Data Base
|
||||
*/
|
||||
SECStatus
|
||||
legacy_DeleteSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *args, PRBool rw)
|
||||
{
|
||||
DBT key;
|
||||
SECStatus rv = SECFailure;
|
||||
DB *pkcs11db = NULL;
|
||||
int ret;
|
||||
|
||||
if (!rw) return SECFailure;
|
||||
|
||||
/* make sure we have a db handle */
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
|
||||
if (pkcs11db == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = secmod_MakeKey(&key,args);
|
||||
if (rv != SECSuccess) goto done;
|
||||
rv = SECFailure;
|
||||
ret = (*pkcs11db->del)(pkcs11db, &key, 0);
|
||||
secmod_FreeKey(&key);
|
||||
if (ret != 0) goto done;
|
||||
|
||||
|
||||
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
||||
if (ret == 0) rv = SECSuccess;
|
||||
|
||||
done:
|
||||
secmod_CloseDB(pkcs11db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a module to the Data base
|
||||
*/
|
||||
SECStatus
|
||||
legacy_AddSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *module, PRBool rw)
|
||||
{
|
||||
DBT key,data;
|
||||
SECStatus rv = SECFailure;
|
||||
DB *pkcs11db = NULL;
|
||||
int ret;
|
||||
|
||||
|
||||
if (!rw) return SECFailure;
|
||||
|
||||
/* make sure we have a db handle */
|
||||
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
|
||||
if (pkcs11db == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = secmod_MakeKey(&key,module);
|
||||
if (rv != SECSuccess) goto done;
|
||||
rv = secmod_EncodeData(&data,module);
|
||||
if (rv != SECSuccess) {
|
||||
secmod_FreeKey(&key);
|
||||
goto done;
|
||||
}
|
||||
rv = SECFailure;
|
||||
ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
|
||||
secmod_FreeKey(&key);
|
||||
secmod_FreeData(&data);
|
||||
if (ret != 0) goto done;
|
||||
|
||||
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
||||
if (ret == 0) rv = SECSuccess;
|
||||
|
||||
done:
|
||||
secmod_CloseDB(pkcs11db);
|
||||
return rv;
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* The following code handles the storage of PKCS 11 modules used by the
|
||||
* NSS. This file is written to abstract away how the modules are
|
||||
* stored so we can deside that later.
|
||||
*/
|
||||
#include "sftkdb.h"
|
||||
#include "sdb.h"
|
||||
#include "prsystem.h"
|
||||
#include "prprf.h"
|
||||
#include "lgglue.h"
|
||||
#include "secerr.h"
|
||||
|
||||
static LGOpenFunc legacy_glue_open = NULL;
|
||||
static LGReadSecmodFunc legacy_glue_readSecmod = NULL;
|
||||
static LGReleaseSecmodFunc legacy_glue_releaseSecmod = NULL;
|
||||
static LGDeleteSecmodFunc legacy_glue_deleteSecmod = NULL;
|
||||
static LGAddSecmodFunc legacy_glue_addSecmod = NULL;
|
||||
static LGShutdownFunc legacy_glue_shutdown = NULL;
|
||||
|
||||
/*
|
||||
* The following 3 functions duplicate the work done by bl_LoadLibrary.
|
||||
* We should make bl_LoadLibrary a global and replace the call to
|
||||
* sftkdb_LoadLibrary(const char *libname) with it.
|
||||
*/
|
||||
#ifdef XP_UNIX
|
||||
#include <unistd.h>
|
||||
#define LG_MAX_LINKS 20
|
||||
static char *
|
||||
sftkdb_resolvePath(const char *orig)
|
||||
{
|
||||
int count = 0;
|
||||
int len =0;
|
||||
int ret = -1;
|
||||
char *resolved = NULL;
|
||||
char *source = NULL;
|
||||
|
||||
len = 1025; /* MAX PATH +1*/
|
||||
if (strlen(orig)+1 > len) {
|
||||
/* PATH TOO LONG */
|
||||
return NULL;
|
||||
}
|
||||
resolved = PORT_Alloc(len);
|
||||
if (!resolved) {
|
||||
return NULL;
|
||||
}
|
||||
source = PORT_Alloc(len);
|
||||
if (!source) {
|
||||
goto loser;
|
||||
}
|
||||
PORT_Strcpy(source, orig);
|
||||
/* Walk down all the links */
|
||||
while ( count++ < LG_MAX_LINKS) {
|
||||
char *tmp;
|
||||
/* swap our previous sorce out with resolved */
|
||||
/* read it */
|
||||
ret = readlink(source, resolved, len-1);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
resolved[ret] = 0;
|
||||
tmp = source; source = resolved; resolved = tmp;
|
||||
}
|
||||
if (count > 1) {
|
||||
ret = 0;
|
||||
}
|
||||
loser:
|
||||
if (resolved) {
|
||||
PORT_Free(resolved);
|
||||
}
|
||||
if (ret < 0) {
|
||||
if (source) {
|
||||
PORT_Free(source);
|
||||
source = NULL;
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static PRLibrary *
|
||||
sftkdb_LoadFromPath(const char *path, const char *libname)
|
||||
{
|
||||
char *c;
|
||||
int pathLen, nameLen, fullPathLen;
|
||||
char *fullPathName = NULL;
|
||||
PRLibSpec libSpec;
|
||||
PRLibrary *lib = NULL;
|
||||
|
||||
|
||||
/* strip of our parent's library name */
|
||||
c = strrchr(path, PR_GetDirectorySeparator());
|
||||
if (!c) {
|
||||
return NULL; /* invalid path */
|
||||
}
|
||||
pathLen = (c-path)+1;
|
||||
nameLen = strlen(libname);
|
||||
fullPathLen = pathLen + nameLen +1;
|
||||
fullPathName = (char *)PORT_Alloc(fullPathLen);
|
||||
if (fullPathName == NULL) {
|
||||
return NULL; /* memory allocation error */
|
||||
}
|
||||
PORT_Memcpy(fullPathName, path, pathLen);
|
||||
PORT_Memcpy(fullPathName+pathLen, libname, nameLen);
|
||||
fullPathName[fullPathLen-1] = 0;
|
||||
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
libSpec.value.pathname = fullPathName;
|
||||
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
PORT_Free(fullPathName);
|
||||
return lib;
|
||||
}
|
||||
|
||||
static PRLibrary *
|
||||
sftkdb_LoadLibrary(const char *libname)
|
||||
{
|
||||
PRLibrary *lib = NULL;
|
||||
PRFuncPtr fn_addr;
|
||||
char *parentLibPath = NULL;
|
||||
|
||||
fn_addr = (PRFuncPtr) &sftkdb_LoadLibrary;
|
||||
parentLibPath = PR_GetLibraryFilePathname(SOFTOKEN_LIB_NAME, fn_addr);
|
||||
|
||||
if (!parentLibPath) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
lib = sftkdb_LoadFromPath(parentLibPath, libname);
|
||||
#ifdef XP_UNIX
|
||||
/* handle symbolic link case */
|
||||
if (!lib) {
|
||||
char *trueParentLibPath = sftkdb_resolvePath(parentLibPath);
|
||||
if (!trueParentLibPath) {
|
||||
goto done;
|
||||
}
|
||||
lib = sftkdb_LoadFromPath(trueParentLibPath, libname);
|
||||
PORT_Free(trueParentLibPath);
|
||||
}
|
||||
#endif
|
||||
PORT_Free(parentLibPath);
|
||||
|
||||
done:
|
||||
/* still couldn't load it, try the generic path */
|
||||
if (!lib) {
|
||||
PRLibSpec libSpec;
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
libSpec.value.pathname = libname;
|
||||
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
}
|
||||
return lib;
|
||||
}
|
||||
|
||||
static PRLibrary *legacy_glue_lib = NULL;
|
||||
static SECStatus
|
||||
sftkdbLoad_Legacy()
|
||||
{
|
||||
PRLibrary *lib = NULL;
|
||||
LGSetCryptFunc setCryptFunction = NULL;
|
||||
|
||||
if (legacy_glue_lib) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
lib = sftkdb_LoadLibrary(SHLIB_PREFIX"lgdbm"SHLIB_VERSION"."SHLIB_SUFFIX);
|
||||
if (lib == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
legacy_glue_open = (LGOpenFunc)PR_FindFunctionSymbol(lib, "legacy_Open");
|
||||
legacy_glue_readSecmod = (LGReadSecmodFunc) PR_FindFunctionSymbol(lib,
|
||||
"legacy_ReadSecmodDB");
|
||||
legacy_glue_releaseSecmod = (LGReleaseSecmodFunc) PR_FindFunctionSymbol(lib,
|
||||
"legacy_ReleaseSecmodDBData");
|
||||
legacy_glue_deleteSecmod = (LGDeleteSecmodFunc) PR_FindFunctionSymbol(lib,
|
||||
"legacy_DeleteSecmodDB");
|
||||
legacy_glue_addSecmod = (LGAddSecmodFunc)PR_FindFunctionSymbol(lib,
|
||||
"legacy_AddSecmodDB");
|
||||
legacy_glue_shutdown = (LGShutdownFunc) PR_FindFunctionSymbol(lib,
|
||||
"legacy_Shutdown");
|
||||
setCryptFunction = (LGSetCryptFunc) PR_FindFunctionSymbol(lib,
|
||||
"legacy_SetCryptFunctions");
|
||||
|
||||
if (!legacy_glue_open || !legacy_glue_readSecmod ||
|
||||
!legacy_glue_releaseSecmod || !legacy_glue_deleteSecmod ||
|
||||
!legacy_glue_addSecmod || !setCryptFunction) {
|
||||
PR_UnloadLibrary(lib);
|
||||
return SECFailure;
|
||||
}
|
||||
setCryptFunction(sftkdb_encrypt_stub,sftkdb_decrypt_stub);
|
||||
legacy_glue_lib = lib;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftkdbCall_open(const char *dir, const char *certPrefix, const char *keyPrefix,
|
||||
int certVersion, int keyVersion, int flags,
|
||||
SDB **certDB, SDB **keyDB)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
rv = sftkdbLoad_Legacy();
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
if (!legacy_glue_open) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*legacy_glue_open)(dir, certPrefix, keyPrefix,
|
||||
certVersion, keyVersion,
|
||||
flags, certDB, keyDB);
|
||||
}
|
||||
|
||||
char **
|
||||
sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *params, PRBool rw)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
rv = sftkdbLoad_Legacy();
|
||||
if (rv != SECSuccess) {
|
||||
return NULL;
|
||||
}
|
||||
if (!legacy_glue_readSecmod) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return (*legacy_glue_readSecmod)(appName, filename, dbname, params, rw);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
sftkdbCall_ReleaseSecmodDBData(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char **moduleSpecList, PRBool rw)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
rv = sftkdbLoad_Legacy();
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
if (!legacy_glue_releaseSecmod) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*legacy_glue_releaseSecmod)(appName, filename, dbname,
|
||||
moduleSpecList, rw);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
sftkdbCall_DeleteSecmodDB(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *args, PRBool rw)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
rv = sftkdbLoad_Legacy();
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
if (!legacy_glue_deleteSecmod) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*legacy_glue_deleteSecmod)(appName, filename, dbname, args, rw);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
sftkdbCall_AddSecmodDB(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *module, PRBool rw)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
rv = sftkdbLoad_Legacy();
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
if (!legacy_glue_addSecmod) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return (*legacy_glue_addSecmod)(appName, filename, dbname, module, rw);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
sftkdbCall_Shutdown(void)
|
||||
{
|
||||
CK_RV crv = CKR_OK;
|
||||
if (legacy_glue_lib) {
|
||||
return CKR_OK;
|
||||
}
|
||||
if (legacy_glue_shutdown) {
|
||||
crv = (*legacy_glue_shutdown)();
|
||||
}
|
||||
PR_UnloadLibrary(legacy_glue_lib);
|
||||
legacy_glue_lib = NULL;
|
||||
legacy_glue_open = NULL;
|
||||
legacy_glue_readSecmod = NULL;
|
||||
legacy_glue_releaseSecmod = NULL;
|
||||
legacy_glue_deleteSecmod = NULL;
|
||||
legacy_glue_addSecmod = NULL;
|
||||
return crv;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* This code defines the glue layer between softoken and the legacy DB library
|
||||
*/
|
||||
#include "sdb.h"
|
||||
|
||||
/*
|
||||
* function prototypes for the callbacks into softoken from the legacyDB
|
||||
*/
|
||||
|
||||
typedef SECStatus (*LGEncryptFunc)(PRArenaPool *arena, SDB *sdb,
|
||||
SECItem *plainText, SECItem **cipherText);
|
||||
typedef SECStatus (*LGDecryptFunc)(SDB *sdb, SECItem *cipherText,
|
||||
SECItem **plainText);
|
||||
|
||||
/*
|
||||
* function prototypes for the exported functions.
|
||||
*/
|
||||
typedef CK_RV (*LGOpenFunc) (const char *dir, const char *certPrefix,
|
||||
const char *keyPrefix,
|
||||
int certVersion, int keyVersion, int flags,
|
||||
SDB **certDB, SDB **keyDB);
|
||||
typedef char ** (*LGReadSecmodFunc)(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname, char *params, PRBool rw);
|
||||
typedef SECStatus (*LGReleaseSecmodFunc)(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname, char **params, PRBool rw);
|
||||
typedef SECStatus (*LGDeleteSecmodFunc)(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname, char *params, PRBool rw);
|
||||
typedef SECStatus (*LGAddSecmodFunc)(const char *appName,
|
||||
const char *filename,
|
||||
const char *dbname, char *params, PRBool rw);
|
||||
typedef SECStatus (*LGShutdownFunc)(void);
|
||||
typedef void (*LGSetCryptFunc)(LGEncryptFunc, LGDecryptFunc);
|
||||
|
||||
|
||||
/*
|
||||
* Softoken Glue Functions
|
||||
*/
|
||||
CK_RV sftkdbCall_open(const char *dir, const char *certPrefix,
|
||||
const char *keyPrefix,
|
||||
int certVersion, int keyVersion, int flags,
|
||||
SDB **certDB, SDB **keyDB);
|
||||
char ** sftkdbCall_ReadSecmodDB(const char *appName, const char *filename,
|
||||
const char *dbname, char *params, PRBool rw);
|
||||
SECStatus sftkdbCall_ReleaseSecmodDBData(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char **moduleSpecList, PRBool rw);
|
||||
SECStatus sftkdbCall_DeleteSecmodDB(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *args, PRBool rw);
|
||||
SECStatus sftkdbCall_AddSecmodDB(const char *appName,
|
||||
const char *filename, const char *dbname,
|
||||
char *module, PRBool rw);
|
||||
CK_RV sftkdbCall_Shutdown(void);
|
||||
|
||||
@@ -1,517 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "lowkeyi.h"
|
||||
#include "secoid.h"
|
||||
#include "secitem.h"
|
||||
#include "secder.h"
|
||||
#include "base64.h"
|
||||
#include "secasn1.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
#include "softoken.h"
|
||||
#endif
|
||||
|
||||
const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYAttribute) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
|
||||
{ SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
|
||||
SEC_AnyTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
|
||||
{ SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
|
||||
};
|
||||
/* ASN1 Templates for new decoder/encoder */
|
||||
const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE,
|
||||
0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
|
||||
{ SEC_ASN1_INTEGER,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,version) },
|
||||
{ SEC_ASN1_INLINE,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
|
||||
SECOID_AlgorithmIDTemplate },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
|
||||
nsslowkey_SetOfAttributeTemplate },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
|
||||
};
|
||||
|
||||
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
|
||||
/* XXX This is just a placeholder for later when we support
|
||||
* generic curves and need full-blown support for parsing EC
|
||||
* parameters. For now, we only support named curves in which
|
||||
* EC params are simply encoded as an object ID and we don't
|
||||
* use nsslowkey_ECParamsTemplate.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
|
||||
{ SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
|
||||
{ SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
||||
/* NOTE: The SECG specification allows the private key structure
|
||||
* to contain curve parameters but recommends that they be stored
|
||||
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
|
||||
* instead.
|
||||
*/
|
||||
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
|
||||
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
|
||||
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
|
||||
{ SEC_ASN1_OCTET_STRING,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
|
||||
/* XXX The following template works for now since we only
|
||||
* support named curves for which the parameters are
|
||||
* encoded as an object ID. When we support generic curves,
|
||||
* we'll need to define nsslowkey_ECParamsTemplate
|
||||
*/
|
||||
#if 1
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
|
||||
SEC_ObjectIDTemplate },
|
||||
#else
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
|
||||
nsslowkey_ECParamsTemplate },
|
||||
#endif
|
||||
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
||||
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
||||
offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
|
||||
SEC_BitStringTemplate },
|
||||
{ 0, }
|
||||
};
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
|
||||
void
|
||||
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.rsa.modulus.type = siUnsignedInteger;
|
||||
key->u.rsa.publicExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.privateExponent.type = siUnsignedInteger;
|
||||
key->u.rsa.prime1.type = siUnsignedInteger;
|
||||
key->u.rsa.prime2.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent1.type = siUnsignedInteger;
|
||||
key->u.rsa.exponent2.type = siUnsignedInteger;
|
||||
key->u.rsa.coefficient.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_pqg_params_for_asn1(PQGParams *params)
|
||||
{
|
||||
params->prime.type = siUnsignedInteger;
|
||||
params->subPrime.type = siUnsignedInteger;
|
||||
params->base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.publicValue.type = siUnsignedInteger;
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
key->u.dsa.params.prime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.subPrime.type = siUnsignedInteger;
|
||||
key->u.dsa.params.base.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dsa.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.dh.prime.type = siUnsignedInteger;
|
||||
key->u.dh.base.type = siUnsignedInteger;
|
||||
key->u.dh.publicValue.type = siUnsignedInteger;
|
||||
key->u.dh.privateValue.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
void
|
||||
prepare_low_ecparams_for_asn1(ECParams *params)
|
||||
{
|
||||
params->DEREncoding.type = siUnsignedInteger;
|
||||
params->curveOID.type = siUnsignedInteger;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
|
||||
{
|
||||
key->u.ec.version.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
|
||||
key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
|
||||
key->u.ec.privateValue.type = siUnsignedInteger;
|
||||
key->u.ec.publicValue.type = siUnsignedInteger;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
if (privk && privk->arena) {
|
||||
PORT_FreeArena(privk->arena, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
if (pubk && pubk->arena) {
|
||||
PORT_FreeArena(pubk->arena, PR_FALSE);
|
||||
}
|
||||
}
|
||||
unsigned
|
||||
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
|
||||
{
|
||||
unsigned char b0;
|
||||
|
||||
/* interpret modulus length as key strength... in
|
||||
* fortezza that's the public key length */
|
||||
|
||||
switch (pubk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = pubk->u.rsa.modulus.data[0];
|
||||
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
|
||||
unsigned char b0;
|
||||
|
||||
switch (privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
b0 = privk->u.rsa.modulus.data[0];
|
||||
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSSLOWKEYPublicKey *
|
||||
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
|
||||
{
|
||||
NSSLOWKEYPublicKey *pubk;
|
||||
PLArenaPool *arena;
|
||||
|
||||
|
||||
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(privk->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
case NSSLOWKEYNullKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof (NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
if (privk->keyType == NSSLOWKEYNullKey) return pubk;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
|
||||
&privk->u.rsa.modulus);
|
||||
if (rv == SECSuccess) {
|
||||
rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
|
||||
&privk->u.rsa.publicExponent);
|
||||
if (rv == SECSuccess)
|
||||
return pubk;
|
||||
}
|
||||
} else {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDSAKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
|
||||
&privk->u.dsa.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
|
||||
&privk->u.dsa.params.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
|
||||
&privk->u.dsa.params.subPrime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
|
||||
&privk->u.dsa.params.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
case NSSLOWKEYDHKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
|
||||
&privk->u.dh.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
|
||||
&privk->u.dh.prime);
|
||||
if (rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
|
||||
&privk->u.dh.base);
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case NSSLOWKEYECKey:
|
||||
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
||||
sizeof(NSSLOWKEYPublicKey));
|
||||
if (pubk != NULL) {
|
||||
SECStatus rv;
|
||||
|
||||
pubk->arena = arena;
|
||||
pubk->keyType = privk->keyType;
|
||||
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
|
||||
&privk->u.ec.publicValue);
|
||||
if (rv != SECSuccess) break;
|
||||
pubk->u.ec.ecParams.arena = arena;
|
||||
/* Copy the rest of the params */
|
||||
rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
|
||||
&(privk->u.ec.ecParams));
|
||||
if (rv == SECSuccess) return pubk;
|
||||
}
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
/* No Fortezza in Low Key implementations (Fortezza keys aren't
|
||||
* stored in our data base */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PORT_FreeArena (arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSSLOWKEYPrivateKey *
|
||||
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
|
||||
{
|
||||
NSSLOWKEYPrivateKey *returnKey = NULL;
|
||||
SECStatus rv = SECFailure;
|
||||
PLArenaPool *poolp;
|
||||
|
||||
if(!privKey) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if(!poolp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
|
||||
if(!returnKey) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
returnKey->keyType = privKey->keyType;
|
||||
returnKey->arena = poolp;
|
||||
|
||||
switch(privKey->keyType) {
|
||||
case NSSLOWKEYRSAKey:
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus),
|
||||
&(privKey->u.rsa.modulus));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version),
|
||||
&(privKey->u.rsa.version));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent),
|
||||
&(privKey->u.rsa.publicExponent));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent),
|
||||
&(privKey->u.rsa.privateExponent));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1),
|
||||
&(privKey->u.rsa.prime1));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2),
|
||||
&(privKey->u.rsa.prime2));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1),
|
||||
&(privKey->u.rsa.exponent1));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2),
|
||||
&(privKey->u.rsa.exponent2));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient),
|
||||
&(privKey->u.rsa.coefficient));
|
||||
if(rv != SECSuccess) break;
|
||||
break;
|
||||
case NSSLOWKEYDSAKey:
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
|
||||
&(privKey->u.dsa.publicValue));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
|
||||
&(privKey->u.dsa.privateValue));
|
||||
if(rv != SECSuccess) break;
|
||||
returnKey->u.dsa.params.arena = poolp;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
|
||||
&(privKey->u.dsa.params.prime));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
|
||||
&(privKey->u.dsa.params.subPrime));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
|
||||
&(privKey->u.dsa.params.base));
|
||||
if(rv != SECSuccess) break;
|
||||
break;
|
||||
case NSSLOWKEYDHKey:
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
|
||||
&(privKey->u.dh.publicValue));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
|
||||
&(privKey->u.dh.privateValue));
|
||||
if(rv != SECSuccess) break;
|
||||
returnKey->u.dsa.params.arena = poolp;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
|
||||
&(privKey->u.dh.prime));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
|
||||
&(privKey->u.dh.base));
|
||||
if(rv != SECSuccess) break;
|
||||
break;
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
case NSSLOWKEYECKey:
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
|
||||
&(privKey->u.ec.version));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
|
||||
&(privKey->u.ec.publicValue));
|
||||
if(rv != SECSuccess) break;
|
||||
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
|
||||
&(privKey->u.ec.privateValue));
|
||||
if(rv != SECSuccess) break;
|
||||
returnKey->u.ec.ecParams.arena = poolp;
|
||||
/* Copy the rest of the params */
|
||||
rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
|
||||
&(privKey->u.ec.ecParams));
|
||||
if (rv != SECSuccess) break;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
default:
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
loser:
|
||||
|
||||
if(rv != SECSuccess) {
|
||||
PORT_FreeArena(poolp, PR_TRUE);
|
||||
returnKey = NULL;
|
||||
}
|
||||
|
||||
return returnKey;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: lowkeyi.h,v 1.10.70.3 2007-02-28 20:44:54 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _LOWKEYI_H_
|
||||
#define _LOWKEYI_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "lowkeyti.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/*
|
||||
* See bugzilla bug 125359
|
||||
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
||||
* all of the templates above that en/decode into integers must be converted
|
||||
* from ASN.1's signed integer type. This is done by marking either the
|
||||
* source or destination (encoding or decoding, respectively) type as
|
||||
* siUnsignedInteger.
|
||||
*/
|
||||
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
|
||||
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
|
||||
extern void prepare_low_ecparams_for_asn1(ECParams *params);
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
/*
|
||||
** Destroy a private key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
|
||||
|
||||
/*
|
||||
** Destroy a public key object.
|
||||
** "key" the object
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
|
||||
|
||||
/*
|
||||
** Return the modulus length of "pubKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
|
||||
|
||||
|
||||
/*
|
||||
** Return the modulus length of "privKey".
|
||||
*/
|
||||
extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
|
||||
|
||||
|
||||
/*
|
||||
** Convert a low private key "privateKey" into a public low key
|
||||
*/
|
||||
extern NSSLOWKEYPublicKey
|
||||
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
|
||||
|
||||
/* Make a copy of a low private key in it's own arena.
|
||||
* a return of NULL indicates an error.
|
||||
*/
|
||||
extern NSSLOWKEYPrivateKey *
|
||||
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey);
|
||||
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _LOWKEYI_H_ */
|
||||
@@ -1,127 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef _LOWKEYTI_H_
|
||||
#define _LOWKEYTI_H_ 1
|
||||
|
||||
#include "blapit.h"
|
||||
#include "prtypes.h"
|
||||
#include "plarena.h"
|
||||
#include "secitem.h"
|
||||
#include "secasn1t.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
/*
|
||||
** Typedef for callback to get a password "key".
|
||||
*/
|
||||
extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
|
||||
extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
|
||||
extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
|
||||
|
||||
/*
|
||||
* PKCS #8 attributes
|
||||
*/
|
||||
struct NSSLOWKEYAttributeStr {
|
||||
SECItem attrType;
|
||||
SECItem *attrValue;
|
||||
};
|
||||
typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
|
||||
|
||||
/*
|
||||
** A PKCS#8 private key info object
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyInfoStr {
|
||||
PLArenaPool *arena;
|
||||
SECItem version;
|
||||
SECAlgorithmID algorithm;
|
||||
SECItem privateKey;
|
||||
NSSLOWKEYAttribute **attributes;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
|
||||
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
|
||||
|
||||
typedef enum {
|
||||
NSSLOWKEYNullKey = 0,
|
||||
NSSLOWKEYRSAKey = 1,
|
||||
NSSLOWKEYDSAKey = 2,
|
||||
NSSLOWKEYDHKey = 4,
|
||||
NSSLOWKEYECKey = 5
|
||||
} NSSLOWKEYType;
|
||||
|
||||
/*
|
||||
** An RSA public key object.
|
||||
*/
|
||||
struct NSSLOWKEYPublicKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType ;
|
||||
union {
|
||||
RSAPublicKey rsa;
|
||||
DSAPublicKey dsa;
|
||||
DHPublicKey dh;
|
||||
ECPublicKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
|
||||
|
||||
/*
|
||||
** Low Level private key object
|
||||
** This is only used by the raw Crypto engines (crypto), keydb (keydb),
|
||||
** and PKCS #11. Everyone else uses the high level key structure.
|
||||
*/
|
||||
struct NSSLOWKEYPrivateKeyStr {
|
||||
PLArenaPool *arena;
|
||||
NSSLOWKEYType keyType;
|
||||
union {
|
||||
RSAPrivateKey rsa;
|
||||
DSAPrivateKey dsa;
|
||||
DHPrivateKey dh;
|
||||
ECPrivateKey ec;
|
||||
} u;
|
||||
};
|
||||
typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
|
||||
|
||||
#endif /* _LOWKEYTI_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,135 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _SECPKCS5_H_
|
||||
#define _SECPKCS5_H_
|
||||
|
||||
#include "plarena.h"
|
||||
#include "secitem.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "hasht.h"
|
||||
|
||||
typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg);
|
||||
|
||||
/* used for V2 PKCS 12 Draft Spec */
|
||||
typedef enum {
|
||||
pbeBitGenIDNull = 0,
|
||||
pbeBitGenCipherKey = 0x01,
|
||||
pbeBitGenCipherIV = 0x02,
|
||||
pbeBitGenIntegrityKey = 0x03
|
||||
} PBEBitGenID;
|
||||
|
||||
typedef enum {
|
||||
NSSPKCS5_PBKDF1 = 0,
|
||||
NSSPKCS5_PBKDF2 = 1,
|
||||
NSSPKCS5_PKCS12_V2 = 2
|
||||
} NSSPKCS5PBEType;
|
||||
|
||||
typedef struct NSSPKCS5PBEParameterStr NSSPKCS5PBEParameter;
|
||||
|
||||
struct NSSPKCS5PBEParameterStr {
|
||||
PRArenaPool *poolp;
|
||||
SECItem salt; /* octet string */
|
||||
SECItem iteration; /* integer */
|
||||
|
||||
/* used locally */
|
||||
int iter;
|
||||
int keyLen;
|
||||
int ivLen;
|
||||
HASH_HashType hashType;
|
||||
NSSPKCS5PBEType pbeType;
|
||||
PBEBitGenID keyID;
|
||||
SECOidTag encAlg;
|
||||
PRBool is2KeyDES;
|
||||
};
|
||||
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
/* Create a PKCS5 Algorithm ID
|
||||
* The algorithm ID is set up using the PKCS #5 parameter structure
|
||||
* algorithm is the PBE algorithm ID for the desired algorithm
|
||||
* pbe is a pbe param block with all the info needed to create the
|
||||
* algorithm id.
|
||||
* If an error occurs or the algorithm specified is not supported
|
||||
* or is not a password based encryption algorithm, NULL is returned.
|
||||
* Otherwise, a pointer to the algorithm id is returned.
|
||||
*/
|
||||
extern SECAlgorithmID *
|
||||
nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm,
|
||||
NSSPKCS5PBEParameter *pbe);
|
||||
|
||||
/*
|
||||
* Convert an Algorithm ID to a PBE Param.
|
||||
* NOTE: this does not suppport PKCS 5 v2 because it's only used for the
|
||||
* keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
|
||||
*/
|
||||
NSSPKCS5PBEParameter *
|
||||
nsspkcs5_AlgidToParam(SECAlgorithmID *algid);
|
||||
|
||||
/*
|
||||
* Convert an Algorithm ID to a PBE Param.
|
||||
* NOTE: this does not suppport PKCS 5 v2 because it's only used for the
|
||||
* keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
|
||||
*/
|
||||
NSSPKCS5PBEParameter *
|
||||
nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator);
|
||||
|
||||
|
||||
/* Encrypt/Decrypt data using password based encryption.
|
||||
* algid is the PBE algorithm identifier,
|
||||
* pwitem is the password,
|
||||
* src is the source for encryption/decryption,
|
||||
* encrypt is PR_TRUE for encryption, PR_FALSE for decryption.
|
||||
* The key and iv are generated based upon PKCS #5 then the src
|
||||
* is either encrypted or decrypted. If an error occurs, NULL
|
||||
* is returned, otherwise the ciphered contents is returned.
|
||||
*/
|
||||
extern SECItem *
|
||||
nsspkcs5_CipherData(NSSPKCS5PBEParameter *, SECItem *pwitem,
|
||||
SECItem *src, PRBool encrypt, PRBool *update);
|
||||
|
||||
extern SECItem *
|
||||
nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *, SECItem *pwitem,
|
||||
SECItem *iv, PRBool faulty3DES);
|
||||
|
||||
/* Destroys PBE parameter */
|
||||
extern void
|
||||
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,98 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
DIRS = legacydb
|
||||
|
||||
REQUIRES = dbm
|
||||
|
||||
LIBRARY_NAME = softokn
|
||||
LIBRARY_VERSION = 3
|
||||
MAPFILE = $(OBJDIR)/softokn.def
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
pkcs11.h \
|
||||
pkcs11f.h \
|
||||
pkcs11p.h \
|
||||
pkcs11t.h \
|
||||
pkcs11n.h \
|
||||
pkcs11u.h \
|
||||
sdb.h \
|
||||
sftkdbt.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
lgglue.h \
|
||||
pk11pars.h \
|
||||
pkcs11ni.h \
|
||||
softoken.h \
|
||||
softoknt.h \
|
||||
softkver.h \
|
||||
$(NULL)
|
||||
|
||||
CSRCS = \
|
||||
ecdecode.c \
|
||||
fipsaudt.c \
|
||||
fipstest.c \
|
||||
fipstokn.c \
|
||||
lgglue.c \
|
||||
lowkey.c \
|
||||
lowpbe.c \
|
||||
padbuf.c \
|
||||
pkcs11.c \
|
||||
pkcs11c.c \
|
||||
pkcs11u.c \
|
||||
rsawrapr.c \
|
||||
sdb.c \
|
||||
sftkdb.c \
|
||||
sftkpars.c \
|
||||
softkver.c \
|
||||
tlsprf.c \
|
||||
$(NULL)
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
DEFINES += -DNSS_ENABLE_ECC
|
||||
endif
|
||||
|
||||
ifdef SQLITE_UNSAFE_THREADS
|
||||
DEFINES += -DSQLITE_UNSAFE_THREADS
|
||||
endif
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "blapit.h"
|
||||
#include "secport.h"
|
||||
#include "secerr.h"
|
||||
|
||||
/*
|
||||
* Prepare a buffer for DES encryption, growing to the appropriate boundary,
|
||||
* filling with the appropriate padding.
|
||||
*
|
||||
* NOTE: If arena is non-NULL, we re-allocate from there, otherwise
|
||||
* we assume (and use) XP memory (re)allocation.
|
||||
*/
|
||||
unsigned char *
|
||||
DES_PadBuffer(PRArenaPool *arena, unsigned char *inbuf, unsigned int inlen,
|
||||
unsigned int *outlen)
|
||||
{
|
||||
unsigned char *outbuf;
|
||||
unsigned int des_len;
|
||||
unsigned int i;
|
||||
unsigned char des_pad_len;
|
||||
|
||||
/*
|
||||
* We need from 1 to DES_KEY_LENGTH bytes -- we *always* grow.
|
||||
* The extra bytes contain the value of the length of the padding:
|
||||
* if we have 2 bytes of padding, then the padding is "0x02, 0x02".
|
||||
*/
|
||||
des_len = (inlen + DES_KEY_LENGTH) & ~(DES_KEY_LENGTH - 1);
|
||||
|
||||
if (arena != NULL) {
|
||||
outbuf = (unsigned char*)PORT_ArenaGrow (arena, inbuf, inlen, des_len);
|
||||
} else {
|
||||
outbuf = (unsigned char*)PORT_Realloc (inbuf, des_len);
|
||||
}
|
||||
|
||||
if (outbuf == NULL) {
|
||||
PORT_SetError (SEC_ERROR_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
des_pad_len = des_len - inlen;
|
||||
for (i = inlen; i < des_len; i++)
|
||||
outbuf[i] = des_pad_len;
|
||||
|
||||
*outlen = des_len;
|
||||
return outbuf;
|
||||
}
|
||||
@@ -1,871 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* The following handles the loading, unloading and management of
|
||||
* various PCKS #11 modules
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* this header file contains routines for parsing PKCS #11 module spec
|
||||
* strings. It contains 'C' code and should only be included in one module.
|
||||
* Currently it is included in both softoken and the wrapper.
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include "pkcs11.h"
|
||||
#include "seccomon.h"
|
||||
#include "prprf.h"
|
||||
#include "secmodt.h"
|
||||
#include "pk11init.h"
|
||||
|
||||
#define SECMOD_ARG_LIBRARY_PARAMETER "library="
|
||||
#define SECMOD_ARG_NAME_PARAMETER "name="
|
||||
#define SECMOD_ARG_MODULE_PARAMETER "parameters="
|
||||
#define SECMOD_ARG_NSS_PARAMETER "NSS="
|
||||
#define SECMOD_ARG_FORTEZZA_FLAG "FORTEZZA"
|
||||
#define SECMOD_ARG_ESCAPE '\\'
|
||||
|
||||
struct secmodargSlotFlagTable {
|
||||
char *name;
|
||||
int len;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
#define SECMOD_DEFAULT_CIPHER_ORDER 0
|
||||
#define SECMOD_DEFAULT_TRUST_ORDER 50
|
||||
|
||||
|
||||
#define SECMOD_ARG_ENTRY(arg,flag) \
|
||||
{ #arg , sizeof(#arg)-1, flag }
|
||||
static struct secmodargSlotFlagTable secmod_argSlotFlagTable[] = {
|
||||
SECMOD_ARG_ENTRY(RSA,SECMOD_RSA_FLAG),
|
||||
SECMOD_ARG_ENTRY(DSA,SECMOD_RSA_FLAG),
|
||||
SECMOD_ARG_ENTRY(RC2,SECMOD_RC4_FLAG),
|
||||
SECMOD_ARG_ENTRY(RC4,SECMOD_RC2_FLAG),
|
||||
SECMOD_ARG_ENTRY(DES,SECMOD_DES_FLAG),
|
||||
SECMOD_ARG_ENTRY(DH,SECMOD_DH_FLAG),
|
||||
SECMOD_ARG_ENTRY(FORTEZZA,SECMOD_FORTEZZA_FLAG),
|
||||
SECMOD_ARG_ENTRY(RC5,SECMOD_RC5_FLAG),
|
||||
SECMOD_ARG_ENTRY(SHA1,SECMOD_SHA1_FLAG),
|
||||
SECMOD_ARG_ENTRY(MD5,SECMOD_MD5_FLAG),
|
||||
SECMOD_ARG_ENTRY(MD2,SECMOD_MD2_FLAG),
|
||||
SECMOD_ARG_ENTRY(SSL,SECMOD_SSL_FLAG),
|
||||
SECMOD_ARG_ENTRY(TLS,SECMOD_TLS_FLAG),
|
||||
SECMOD_ARG_ENTRY(AES,SECMOD_AES_FLAG),
|
||||
SECMOD_ARG_ENTRY(Camellia,SECMOD_CAMELLIA_FLAG),
|
||||
SECMOD_ARG_ENTRY(PublicCerts,SECMOD_FRIENDLY_FLAG),
|
||||
SECMOD_ARG_ENTRY(RANDOM,SECMOD_RANDOM_FLAG),
|
||||
};
|
||||
|
||||
#define SECMOD_HANDLE_STRING_ARG(param,target,value,command) \
|
||||
if (PORT_Strncasecmp(param,value,sizeof(value)-1) == 0) { \
|
||||
param += sizeof(value)-1; \
|
||||
if (target) PORT_Free(target); \
|
||||
target = secmod_argFetchValue(param,&next); \
|
||||
param += next; \
|
||||
command ;\
|
||||
} else
|
||||
|
||||
#define SECMOD_HANDLE_FINAL_ARG(param) \
|
||||
{ param = secmod_argSkipParameter(param); } param = secmod_argStrip(param);
|
||||
|
||||
|
||||
static int secmod_argSlotFlagTableSize =
|
||||
sizeof(secmod_argSlotFlagTable)/sizeof(secmod_argSlotFlagTable[0]);
|
||||
|
||||
|
||||
static PRBool secmod_argGetPair(char c) {
|
||||
switch (c) {
|
||||
case '\'': return c;
|
||||
case '\"': return c;
|
||||
case '<': return '>';
|
||||
case '{': return '}';
|
||||
case '[': return ']';
|
||||
case '(': return ')';
|
||||
default: break;
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
|
||||
static PRBool secmod_argIsBlank(char c) {
|
||||
return isspace(c);
|
||||
}
|
||||
|
||||
static PRBool secmod_argIsEscape(char c) {
|
||||
return c == '\\';
|
||||
}
|
||||
|
||||
static PRBool secmod_argIsQuote(char c) {
|
||||
switch (c) {
|
||||
case '\'':
|
||||
case '\"':
|
||||
case '<':
|
||||
case '{': /* } end curly to keep vi bracket matching working */
|
||||
case '(': /* ) */
|
||||
case '[': /* ] */ return PR_TRUE;
|
||||
default: break;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool secmod_argHasChar(char *v, char c)
|
||||
{
|
||||
for ( ;*v; v++) {
|
||||
if (*v == c) return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool secmod_argHasBlanks(char *v)
|
||||
{
|
||||
for ( ;*v; v++) {
|
||||
if (secmod_argIsBlank(*v)) return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static char *secmod_argStrip(char *c) {
|
||||
while (*c && secmod_argIsBlank(*c)) c++;
|
||||
return c;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_argFindEnd(char *string) {
|
||||
char endChar = ' ';
|
||||
PRBool lastEscape = PR_FALSE;
|
||||
|
||||
if (secmod_argIsQuote(*string)) {
|
||||
endChar = secmod_argGetPair(*string);
|
||||
string++;
|
||||
}
|
||||
|
||||
for (;*string; string++) {
|
||||
if (lastEscape) {
|
||||
lastEscape = PR_FALSE;
|
||||
continue;
|
||||
}
|
||||
if (secmod_argIsEscape(*string) && !lastEscape) {
|
||||
lastEscape = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
if ((endChar == ' ') && secmod_argIsBlank(*string)) break;
|
||||
if (*string == endChar) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_argFetchValue(char *string, int *pcount)
|
||||
{
|
||||
char *end = secmod_argFindEnd(string);
|
||||
char *retString, *copyString;
|
||||
PRBool lastEscape = PR_FALSE;
|
||||
int len;
|
||||
|
||||
len = end - string;
|
||||
if (len == 0) {
|
||||
*pcount = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copyString = retString = (char *)PORT_Alloc(len+1);
|
||||
|
||||
if (*end) len++;
|
||||
*pcount = len;
|
||||
if (retString == NULL) return NULL;
|
||||
|
||||
|
||||
if (secmod_argIsQuote(*string)) string++;
|
||||
for (; string < end; string++) {
|
||||
if (secmod_argIsEscape(*string) && !lastEscape) {
|
||||
lastEscape = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
lastEscape = PR_FALSE;
|
||||
*copyString++ = *string;
|
||||
}
|
||||
*copyString = 0;
|
||||
return retString;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_argSkipParameter(char *string)
|
||||
{
|
||||
char *end;
|
||||
/* look for the end of the <name>= */
|
||||
for (;*string; string++) {
|
||||
if (*string == '=') { string++; break; }
|
||||
if (secmod_argIsBlank(*string)) return(string);
|
||||
}
|
||||
|
||||
end = secmod_argFindEnd(string);
|
||||
if (*end) end++;
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
static SECStatus
|
||||
secmod_argParseModuleSpec(char *modulespec, char **lib, char **mod,
|
||||
char **parameters, char **nss)
|
||||
{
|
||||
int next;
|
||||
modulespec = secmod_argStrip(modulespec);
|
||||
|
||||
*lib = *mod = *parameters = *nss = 0;
|
||||
|
||||
while (*modulespec) {
|
||||
SECMOD_HANDLE_STRING_ARG(modulespec,*lib,SECMOD_ARG_LIBRARY_PARAMETER,;)
|
||||
SECMOD_HANDLE_STRING_ARG(modulespec,*mod,SECMOD_ARG_NAME_PARAMETER,;)
|
||||
SECMOD_HANDLE_STRING_ARG(modulespec,*parameters,
|
||||
SECMOD_ARG_MODULE_PARAMETER,;)
|
||||
SECMOD_HANDLE_STRING_ARG(modulespec,*nss,SECMOD_ARG_NSS_PARAMETER,;)
|
||||
SECMOD_HANDLE_FINAL_ARG(modulespec)
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
secmod_argGetParamValue(char *paramName,char *parameters)
|
||||
{
|
||||
char searchValue[256];
|
||||
int paramLen = strlen(paramName);
|
||||
char *returnValue = NULL;
|
||||
int next;
|
||||
|
||||
if ((parameters == NULL) || (*parameters == 0)) return NULL;
|
||||
|
||||
PORT_Assert(paramLen+2 < sizeof(searchValue));
|
||||
|
||||
PORT_Strcpy(searchValue,paramName);
|
||||
PORT_Strcat(searchValue,"=");
|
||||
while (*parameters) {
|
||||
if (PORT_Strncasecmp(parameters,searchValue,paramLen+1) == 0) {
|
||||
parameters += paramLen+1;
|
||||
returnValue = secmod_argFetchValue(parameters,&next);
|
||||
break;
|
||||
} else {
|
||||
parameters = secmod_argSkipParameter(parameters);
|
||||
}
|
||||
parameters = secmod_argStrip(parameters);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
secmod_argNextFlag(char *flags)
|
||||
{
|
||||
for (; *flags ; flags++) {
|
||||
if (*flags == ',') {
|
||||
flags++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
secmod_argHasFlag(char *label, char *flag, char *parameters)
|
||||
{
|
||||
char *flags,*index;
|
||||
int len = strlen(flag);
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
flags = secmod_argGetParamValue(label,parameters);
|
||||
if (flags == NULL) return PR_FALSE;
|
||||
|
||||
for (index=flags; *index; index=secmod_argNextFlag(index)) {
|
||||
if (PORT_Strncasecmp(index,flag,len) == 0) {
|
||||
found=PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PORT_Free(flags);
|
||||
return found;
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_argSetNewCipherFlags(unsigned long *newCiphers,char *cipherList)
|
||||
{
|
||||
newCiphers[0] = newCiphers[1] = 0;
|
||||
if ((cipherList == NULL) || (*cipherList == 0)) return;
|
||||
|
||||
for (;*cipherList; cipherList=secmod_argNextFlag(cipherList)) {
|
||||
if (PORT_Strncasecmp(cipherList,SECMOD_ARG_FORTEZZA_FLAG,
|
||||
sizeof(SECMOD_ARG_FORTEZZA_FLAG)-1) == 0) {
|
||||
newCiphers[0] |= SECMOD_FORTEZZA_FLAG;
|
||||
}
|
||||
|
||||
/* add additional flags here as necessary */
|
||||
/* direct bit mapping escape */
|
||||
if (*cipherList == 0) {
|
||||
if (cipherList[1] == 'l') {
|
||||
newCiphers[1] |= atoi(&cipherList[2]);
|
||||
} else {
|
||||
newCiphers[0] |= atoi(&cipherList[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
|
||||
*/
|
||||
static long
|
||||
secmod_argDecodeNumber(char *num)
|
||||
{
|
||||
int radix = 10;
|
||||
unsigned long value = 0;
|
||||
long retValue = 0;
|
||||
int sign = 1;
|
||||
int digit;
|
||||
|
||||
if (num == NULL) return retValue;
|
||||
|
||||
num = secmod_argStrip(num);
|
||||
|
||||
if (*num == '-') {
|
||||
sign = -1;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (*num == '0') {
|
||||
radix = 8;
|
||||
num++;
|
||||
if ((*num == 'x') || (*num == 'X')) {
|
||||
radix = 16;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for ( ;*num; num++ ) {
|
||||
if (isdigit(*num)) {
|
||||
digit = *num - '0';
|
||||
} else if ((*num >= 'a') && (*num <= 'f')) {
|
||||
digit = *num - 'a' + 10;
|
||||
} else if ((*num >= 'A') && (*num <= 'F')) {
|
||||
digit = *num - 'A' + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (digit >= radix) break;
|
||||
value = value*radix + digit;
|
||||
}
|
||||
|
||||
retValue = ((int) value) * sign;
|
||||
return retValue;
|
||||
}
|
||||
|
||||
static long
|
||||
secmod_argReadLong(char *label,char *params, long defValue, PRBool *isdefault)
|
||||
{
|
||||
char *value;
|
||||
long retValue;
|
||||
if (isdefault) *isdefault = PR_FALSE;
|
||||
|
||||
value = secmod_argGetParamValue(label,params);
|
||||
if (value == NULL) {
|
||||
if (isdefault) *isdefault = PR_TRUE;
|
||||
return defValue;
|
||||
}
|
||||
retValue = secmod_argDecodeNumber(value);
|
||||
if (value) PORT_Free(value);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long
|
||||
secmod_argSlotFlags(char *label,char *params)
|
||||
{
|
||||
char *flags,*index;
|
||||
unsigned long retValue = 0;
|
||||
int i;
|
||||
PRBool all = PR_FALSE;
|
||||
|
||||
flags = secmod_argGetParamValue(label,params);
|
||||
if (flags == NULL) return 0;
|
||||
|
||||
if (PORT_Strcasecmp(flags,"all") == 0) all = PR_TRUE;
|
||||
|
||||
for (index=flags; *index; index=secmod_argNextFlag(index)) {
|
||||
for (i=0; i < secmod_argSlotFlagTableSize; i++) {
|
||||
if (all || (PORT_Strncasecmp(index, secmod_argSlotFlagTable[i].name,
|
||||
secmod_argSlotFlagTable[i].len) == 0)) {
|
||||
retValue |= secmod_argSlotFlagTable[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
PORT_Free(flags);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
secmod_argDecodeSingleSlotInfo(char *name, char *params,
|
||||
PK11PreSlotInfo *slotInfo)
|
||||
{
|
||||
char *askpw;
|
||||
|
||||
slotInfo->slotID=secmod_argDecodeNumber(name);
|
||||
slotInfo->defaultFlags=secmod_argSlotFlags("slotFlags",params);
|
||||
slotInfo->timeout=secmod_argReadLong("timeout",params, 0, NULL);
|
||||
|
||||
askpw = secmod_argGetParamValue("askpw",params);
|
||||
slotInfo->askpw = 0;
|
||||
|
||||
if (askpw) {
|
||||
if (PORT_Strcasecmp(askpw,"every") == 0) {
|
||||
slotInfo->askpw = -1;
|
||||
} else if (PORT_Strcasecmp(askpw,"timeout") == 0) {
|
||||
slotInfo->askpw = 1;
|
||||
}
|
||||
PORT_Free(askpw);
|
||||
slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS;
|
||||
}
|
||||
slotInfo->hasRootCerts = secmod_argHasFlag("rootFlags", "hasRootCerts",
|
||||
params);
|
||||
slotInfo->hasRootTrust = secmod_argHasFlag("rootFlags", "hasRootTrust",
|
||||
params);
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_argGetName(char *inString, int *next)
|
||||
{
|
||||
char *name=NULL;
|
||||
char *string;
|
||||
int len;
|
||||
|
||||
/* look for the end of the <name>= */
|
||||
for (string = inString;*string; string++) {
|
||||
if (*string == '=') { break; }
|
||||
if (secmod_argIsBlank(*string)) break;
|
||||
}
|
||||
|
||||
len = string - inString;
|
||||
|
||||
*next = len;
|
||||
if (*string == '=') (*next) += 1;
|
||||
if (len > 0) {
|
||||
name = PORT_Alloc(len+1);
|
||||
PORT_Strncpy(name,inString,len);
|
||||
name[len] = 0;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static PK11PreSlotInfo *
|
||||
secmod_argParseSlotInfo(PRArenaPool *arena, char *slotParams, int *retCount)
|
||||
{
|
||||
char *slotIndex;
|
||||
PK11PreSlotInfo *slotInfo = NULL;
|
||||
int i=0,count = 0,next;
|
||||
|
||||
*retCount = 0;
|
||||
if ((slotParams == NULL) || (*slotParams == 0)) return NULL;
|
||||
|
||||
/* first count the number of slots */
|
||||
for (slotIndex = secmod_argStrip(slotParams); *slotIndex;
|
||||
slotIndex = secmod_argStrip(secmod_argSkipParameter(slotIndex))) {
|
||||
count++;
|
||||
}
|
||||
|
||||
/* get the data structures */
|
||||
if (arena) {
|
||||
slotInfo = (PK11PreSlotInfo *)
|
||||
PORT_ArenaAlloc(arena,count*sizeof(PK11PreSlotInfo));
|
||||
PORT_Memset(slotInfo,0,count*sizeof(PK11PreSlotInfo));
|
||||
} else {
|
||||
slotInfo = (PK11PreSlotInfo *)
|
||||
PORT_ZAlloc(count*sizeof(PK11PreSlotInfo));
|
||||
}
|
||||
if (slotInfo == NULL) return NULL;
|
||||
|
||||
for (slotIndex = secmod_argStrip(slotParams), i = 0;
|
||||
*slotIndex && i < count ; ) {
|
||||
char *name;
|
||||
name = secmod_argGetName(slotIndex,&next);
|
||||
slotIndex += next;
|
||||
|
||||
if (!secmod_argIsBlank(*slotIndex)) {
|
||||
char *args = secmod_argFetchValue(slotIndex,&next);
|
||||
slotIndex += next;
|
||||
if (args) {
|
||||
secmod_argDecodeSingleSlotInfo(name,args,&slotInfo[i]);
|
||||
i++;
|
||||
PORT_Free(args);
|
||||
}
|
||||
}
|
||||
if (name) PORT_Free(name);
|
||||
slotIndex = secmod_argStrip(slotIndex);
|
||||
}
|
||||
*retCount = i;
|
||||
return slotInfo;
|
||||
}
|
||||
|
||||
static char *secmod_nullString = "";
|
||||
|
||||
static char *
|
||||
secmod_formatValue(PRArenaPool *arena, char *value, char quote)
|
||||
{
|
||||
char *vp,*vp2,*retval;
|
||||
int size = 0, escapes = 0;
|
||||
|
||||
for (vp=value; *vp ;vp++) {
|
||||
if ((*vp == quote) || (*vp == SECMOD_ARG_ESCAPE)) escapes++;
|
||||
size++;
|
||||
}
|
||||
if (arena) {
|
||||
retval = PORT_ArenaZAlloc(arena,size+escapes+1);
|
||||
} else {
|
||||
retval = PORT_ZAlloc(size+escapes+1);
|
||||
}
|
||||
if (retval == NULL) return NULL;
|
||||
vp2 = retval;
|
||||
for (vp=value; *vp; vp++) {
|
||||
if ((*vp == quote) || (*vp == SECMOD_ARG_ESCAPE))
|
||||
*vp2++ = SECMOD_ARG_ESCAPE;
|
||||
*vp2++ = *vp;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static char *secmod_formatPair(char *name,char *value, char quote)
|
||||
{
|
||||
char openQuote = quote;
|
||||
char closeQuote = secmod_argGetPair(quote);
|
||||
char *newValue = NULL;
|
||||
char *returnValue;
|
||||
PRBool need_quote = PR_FALSE;
|
||||
|
||||
if (!value || (*value == 0)) return secmod_nullString;
|
||||
|
||||
if (secmod_argHasBlanks(value) || secmod_argIsQuote(value[0]))
|
||||
need_quote=PR_TRUE;
|
||||
|
||||
if ((need_quote && secmod_argHasChar(value,closeQuote))
|
||||
|| secmod_argHasChar(value,SECMOD_ARG_ESCAPE)) {
|
||||
value = newValue = secmod_formatValue(NULL, value,quote);
|
||||
if (newValue == NULL) return secmod_nullString;
|
||||
}
|
||||
if (need_quote) {
|
||||
returnValue = PR_smprintf("%s=%c%s%c",name,openQuote,value,closeQuote);
|
||||
} else {
|
||||
returnValue = PR_smprintf("%s=%s",name,value);
|
||||
}
|
||||
if (returnValue == NULL) returnValue = secmod_nullString;
|
||||
|
||||
if (newValue) PORT_Free(newValue);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
static char *secmod_formatIntPair(char *name, unsigned long value,
|
||||
unsigned long def)
|
||||
{
|
||||
char *returnValue;
|
||||
|
||||
if (value == def) return secmod_nullString;
|
||||
|
||||
returnValue = PR_smprintf("%s=%d",name,value);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
static void
|
||||
secmod_freePair(char *pair)
|
||||
{
|
||||
if (pair && pair != secmod_nullString) {
|
||||
PR_smprintf_free(pair);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_FLAG_SIZE sizeof("internal")+sizeof("FIPS")+sizeof("moduleDB")+\
|
||||
sizeof("moduleDBOnly")+sizeof("critical")
|
||||
static char *
|
||||
secmod_mkNSSFlags(PRBool internal, PRBool isFIPS,
|
||||
PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical)
|
||||
{
|
||||
char *flags = (char *)PORT_ZAlloc(MAX_FLAG_SIZE);
|
||||
PRBool first = PR_TRUE;
|
||||
|
||||
PORT_Memset(flags,0,MAX_FLAG_SIZE);
|
||||
if (internal) {
|
||||
PORT_Strcat(flags,"internal");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (isFIPS) {
|
||||
if (!first) PORT_Strcat(flags,",");
|
||||
PORT_Strcat(flags,"FIPS");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (isModuleDB) {
|
||||
if (!first) PORT_Strcat(flags,",");
|
||||
PORT_Strcat(flags,"moduleDB");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (isModuleDBOnly) {
|
||||
if (!first) PORT_Strcat(flags,",");
|
||||
PORT_Strcat(flags,"moduleDBOnly");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (isCritical) {
|
||||
if (!first) PORT_Strcat(flags,",");
|
||||
PORT_Strcat(flags,"critical");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
|
||||
{
|
||||
char *cipher = NULL;
|
||||
int i;
|
||||
|
||||
for (i=0; i < sizeof(ssl0)*8; i++) {
|
||||
if (ssl0 & (1<<i)) {
|
||||
char *string;
|
||||
if ((1<<i) == SECMOD_FORTEZZA_FLAG) {
|
||||
string = PR_smprintf("%s","FORTEZZA");
|
||||
} else {
|
||||
string = PR_smprintf("0h0x%08x",1<<i);
|
||||
}
|
||||
if (cipher) {
|
||||
char *tmp;
|
||||
tmp = PR_smprintf("%s,%s",cipher,string);
|
||||
PR_smprintf_free(cipher);
|
||||
PR_smprintf_free(string);
|
||||
cipher = tmp;
|
||||
} else {
|
||||
cipher = string;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i < sizeof(ssl0)*8; i++) {
|
||||
if (ssl1 & (1<<i)) {
|
||||
if (cipher) {
|
||||
char *tmp;
|
||||
tmp = PR_smprintf("%s,0l0x%08x",cipher,1<<i);
|
||||
PR_smprintf_free(cipher);
|
||||
cipher = tmp;
|
||||
} else {
|
||||
cipher = PR_smprintf("0l0x%08x",1<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cipher;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_mkSlotFlags(unsigned long defaultFlags)
|
||||
{
|
||||
char *flags=NULL;
|
||||
int i,j;
|
||||
|
||||
for (i=0; i < sizeof(defaultFlags)*8; i++) {
|
||||
if (defaultFlags & (1<<i)) {
|
||||
char *string = NULL;
|
||||
|
||||
for (j=0; j < secmod_argSlotFlagTableSize; j++) {
|
||||
if (secmod_argSlotFlagTable[j].value == ( 1UL << i )) {
|
||||
string = secmod_argSlotFlagTable[j].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (string) {
|
||||
if (flags) {
|
||||
char *tmp;
|
||||
tmp = PR_smprintf("%s,%s",flags,string);
|
||||
PR_smprintf_free(flags);
|
||||
flags = tmp;
|
||||
} else {
|
||||
flags = PR_smprintf("%s",string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
#define SECMOD_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts")+sizeof("hasRootTrust")
|
||||
|
||||
static char *
|
||||
secmod_mkRootFlags(PRBool hasRootCerts, PRBool hasRootTrust)
|
||||
{
|
||||
char *flags= (char *)PORT_ZAlloc(SECMOD_MAX_ROOT_FLAG_SIZE);
|
||||
PRBool first = PR_TRUE;
|
||||
|
||||
PORT_Memset(flags,0,SECMOD_MAX_ROOT_FLAG_SIZE);
|
||||
if (hasRootCerts) {
|
||||
PORT_Strcat(flags,"hasRootCerts");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
if (hasRootTrust) {
|
||||
if (!first) PORT_Strcat(flags,",");
|
||||
PORT_Strcat(flags,"hasRootTrust");
|
||||
first = PR_FALSE;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_mkSlotString(unsigned long slotID, unsigned long defaultFlags,
|
||||
unsigned long timeout, unsigned char askpw_in,
|
||||
PRBool hasRootCerts, PRBool hasRootTrust) {
|
||||
char *askpw,*flags,*rootFlags,*slotString;
|
||||
char *flagPair,*rootFlagsPair;
|
||||
|
||||
switch (askpw_in) {
|
||||
case 0xff:
|
||||
askpw = "every";
|
||||
break;
|
||||
case 1:
|
||||
askpw = "timeout";
|
||||
break;
|
||||
default:
|
||||
askpw = "any";
|
||||
break;
|
||||
}
|
||||
flags = secmod_mkSlotFlags(defaultFlags);
|
||||
rootFlags = secmod_mkRootFlags(hasRootCerts,hasRootTrust);
|
||||
flagPair=secmod_formatPair("slotFlags",flags,'\'');
|
||||
rootFlagsPair=secmod_formatPair("rootFlags",rootFlags,'\'');
|
||||
if (flags) PR_smprintf_free(flags);
|
||||
if (rootFlags) PORT_Free(rootFlags);
|
||||
if (defaultFlags & PK11_OWN_PW_DEFAULTS) {
|
||||
slotString = PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
|
||||
(PRUint32)slotID,flagPair,askpw,timeout,
|
||||
rootFlagsPair);
|
||||
} else {
|
||||
slotString = PR_smprintf("0x%08lx=[%s %s]",
|
||||
(PRUint32)slotID,flagPair,rootFlagsPair);
|
||||
}
|
||||
secmod_freePair(flagPair);
|
||||
secmod_freePair(rootFlagsPair);
|
||||
return slotString;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_mkNSS(char **slotStrings, int slotCount, PRBool internal, PRBool isFIPS,
|
||||
PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical,
|
||||
unsigned long trustOrder, unsigned long cipherOrder,
|
||||
unsigned long ssl0, unsigned long ssl1) {
|
||||
int slotLen, i;
|
||||
char *slotParams, *ciphers, *nss, *nssFlags, *tmp;
|
||||
char *trustOrderPair,*cipherOrderPair,*slotPair,*cipherPair,*flagPair;
|
||||
|
||||
|
||||
/* now let's build up the string
|
||||
* first the slot infos
|
||||
*/
|
||||
slotLen=0;
|
||||
for (i=0; i < (int)slotCount; i++) {
|
||||
slotLen += PORT_Strlen(slotStrings[i])+1;
|
||||
}
|
||||
slotLen += 1; /* space for the final NULL */
|
||||
|
||||
slotParams = (char *)PORT_ZAlloc(slotLen);
|
||||
PORT_Memset(slotParams,0,slotLen);
|
||||
for (i=0; i < (int)slotCount; i++) {
|
||||
PORT_Strcat(slotParams,slotStrings[i]);
|
||||
PORT_Strcat(slotParams," ");
|
||||
PR_smprintf_free(slotStrings[i]);
|
||||
slotStrings[i]=NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* now the NSS structure
|
||||
*/
|
||||
nssFlags = secmod_mkNSSFlags(internal,isFIPS,isModuleDB,isModuleDBOnly,
|
||||
isCritical);
|
||||
/* for now only the internal module is critical */
|
||||
ciphers = secmod_mkCipherFlags(ssl0, ssl1);
|
||||
|
||||
trustOrderPair=secmod_formatIntPair("trustOrder",trustOrder,
|
||||
SECMOD_DEFAULT_TRUST_ORDER);
|
||||
cipherOrderPair=secmod_formatIntPair("cipherOrder",cipherOrder,
|
||||
SECMOD_DEFAULT_CIPHER_ORDER);
|
||||
slotPair=secmod_formatPair("slotParams",slotParams,'{'); /* } */
|
||||
if (slotParams) PORT_Free(slotParams);
|
||||
cipherPair=secmod_formatPair("ciphers",ciphers,'\'');
|
||||
if (ciphers) PR_smprintf_free(ciphers);
|
||||
flagPair=secmod_formatPair("Flags",nssFlags,'\'');
|
||||
if (nssFlags) PORT_Free(nssFlags);
|
||||
nss = PR_smprintf("%s %s %s %s %s",trustOrderPair,
|
||||
cipherOrderPair,slotPair,cipherPair,flagPair);
|
||||
secmod_freePair(trustOrderPair);
|
||||
secmod_freePair(cipherOrderPair);
|
||||
secmod_freePair(slotPair);
|
||||
secmod_freePair(cipherPair);
|
||||
secmod_freePair(flagPair);
|
||||
tmp = secmod_argStrip(nss);
|
||||
if (*tmp == '\0') {
|
||||
PR_smprintf_free(nss);
|
||||
nss = NULL;
|
||||
}
|
||||
return nss;
|
||||
}
|
||||
|
||||
static char *
|
||||
secmod_mkNewModuleSpec(char *dllName, char *commonName, char *parameters,
|
||||
char *NSS) {
|
||||
char *moduleSpec;
|
||||
char *lib,*name,*param,*nss;
|
||||
|
||||
/*
|
||||
* now the final spec
|
||||
*/
|
||||
lib = secmod_formatPair("library",dllName,'\"');
|
||||
name = secmod_formatPair("name",commonName,'\"');
|
||||
param = secmod_formatPair("parameters",parameters,'\"');
|
||||
nss = secmod_formatPair("NSS",NSS,'\"');
|
||||
moduleSpec = PR_smprintf("%s %s %s %s", lib,name,param,nss);
|
||||
secmod_freePair(lib);
|
||||
secmod_freePair(name);
|
||||
secmod_freePair(param);
|
||||
secmod_freePair(nss);
|
||||
return (moduleSpec);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,323 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* RSA Labs
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
|
||||
* is granted provided that it is identified as "RSA Security In.c Public-Key
|
||||
* Cryptography Standards (PKCS)" in all material mentioning or referencing
|
||||
* this document.
|
||||
*
|
||||
* The latest version of this header can be found at:
|
||||
* http://www.rsalabs.com/pkcs/pkcs-11/index.html
|
||||
*/
|
||||
#ifndef _PKCS11_H_
|
||||
#define _PKCS11_H_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Before including this file (pkcs11.h) (or pkcs11t.h by
|
||||
* itself), 6 platform-specific macros must be defined. These
|
||||
* macros are described below, and typical definitions for them
|
||||
* are also given. Be advised that these definitions can depend
|
||||
* on both the platform and the compiler used (and possibly also
|
||||
* on whether a PKCS #11 library is linked statically or
|
||||
* dynamically).
|
||||
*
|
||||
* In addition to defining these 6 macros, the packing convention
|
||||
* for PKCS #11 structures should be set. The PKCS #11
|
||||
* convention on packing is that structures should be 1-byte
|
||||
* aligned.
|
||||
*
|
||||
* In a Win32 environment, this might be done by using the
|
||||
* following preprocessor directive before including pkcs11.h
|
||||
* or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(push, cryptoki, 1)
|
||||
*
|
||||
* and using the following preprocessor directive after including
|
||||
* pkcs11.h or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(pop, cryptoki)
|
||||
*
|
||||
* In a Win16 environment, this might be done by using the
|
||||
* following preprocessor directive before including pkcs11.h
|
||||
* or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(1)
|
||||
*
|
||||
* In a UNIX environment, you're on your own here. You might
|
||||
* not need to do anything.
|
||||
*
|
||||
*
|
||||
* Now for the macros:
|
||||
*
|
||||
*
|
||||
* 1. CK_PTR: The indirection string for making a pointer to an
|
||||
* object. It can be used like this:
|
||||
*
|
||||
* typedef CK_BYTE CK_PTR CK_BYTE_PTR;
|
||||
*
|
||||
* In a Win32 environment, it might be defined by
|
||||
*
|
||||
* #define CK_PTR *
|
||||
*
|
||||
* In a Win16 environment, it might be defined by
|
||||
*
|
||||
* #define CK_PTR far *
|
||||
*
|
||||
* In a UNIX environment, it might be defined by
|
||||
*
|
||||
* #define CK_PTR *
|
||||
*
|
||||
*
|
||||
* 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
|
||||
* an exportable PKCS #11 library function definition out of a
|
||||
* return type and a function name. It should be used in the
|
||||
* following fashion to define the exposed PKCS #11 functions in
|
||||
* a PKCS #11 library:
|
||||
*
|
||||
* CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
|
||||
* CK_VOID_PTR pReserved
|
||||
* )
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* For defining a function in a Win32 PKCS #11 .dll, it might be
|
||||
* defined by
|
||||
*
|
||||
* #define CK_DEFINE_FUNCTION(returnType, name) \
|
||||
* returnType __declspec(dllexport) name
|
||||
*
|
||||
* For defining a function in a Win16 PKCS #11 .dll, it might be
|
||||
* defined by
|
||||
*
|
||||
* #define CK_DEFINE_FUNCTION(returnType, name) \
|
||||
* returnType __export _far _pascal name
|
||||
*
|
||||
* In a UNIX environment, it might be defined by
|
||||
*
|
||||
* #define CK_DEFINE_FUNCTION(returnType, name) \
|
||||
* returnType name
|
||||
*
|
||||
*
|
||||
* 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
|
||||
* an importable PKCS #11 library function declaration out of a
|
||||
* return type and a function name. It should be used in the
|
||||
* following fashion:
|
||||
*
|
||||
* extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
|
||||
* CK_VOID_PTR pReserved
|
||||
* );
|
||||
*
|
||||
* For declaring a function in a Win32 PKCS #11 .dll, it might
|
||||
* be defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType __declspec(dllimport) name
|
||||
*
|
||||
* For declaring a function in a Win16 PKCS #11 .dll, it might
|
||||
* be defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType __export _far _pascal name
|
||||
*
|
||||
* In a UNIX environment, it might be defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType name
|
||||
*
|
||||
*
|
||||
* 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
|
||||
* which makes a PKCS #11 API function pointer declaration or
|
||||
* function pointer type declaration out of a return type and a
|
||||
* function name. It should be used in the following fashion:
|
||||
*
|
||||
* // Define funcPtr to be a pointer to a PKCS #11 API function
|
||||
* // taking arguments args and returning CK_RV.
|
||||
* CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
|
||||
*
|
||||
* or
|
||||
*
|
||||
* // Define funcPtrType to be the type of a pointer to a
|
||||
* // PKCS #11 API function taking arguments args and returning
|
||||
* // CK_RV, and then define funcPtr to be a variable of type
|
||||
* // funcPtrType.
|
||||
* typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
|
||||
* funcPtrType funcPtr;
|
||||
*
|
||||
* For accessing functions in a Win32 PKCS #11 .dll, in might be
|
||||
* defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType __declspec(dllimport) (* name)
|
||||
*
|
||||
* For accessing functions in a Win16 PKCS #11 .dll, it might be
|
||||
* defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType __export _far _pascal (* name)
|
||||
*
|
||||
* In a UNIX environment, it might be defined by
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
*
|
||||
* 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
|
||||
* a function pointer type for an application callback out of
|
||||
* a return type for the callback and a name for the callback.
|
||||
* It should be used in the following fashion:
|
||||
*
|
||||
* CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
|
||||
*
|
||||
* to declare a function pointer, myCallback, to a callback
|
||||
* which takes arguments args and returns a CK_RV. It can also
|
||||
* be used like this:
|
||||
*
|
||||
* typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
|
||||
* myCallbackType myCallback;
|
||||
*
|
||||
* In a Win32 environment, it might be defined by
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
* In a Win16 environment, it might be defined by
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType _far _pascal (* name)
|
||||
*
|
||||
* In a UNIX environment, it might be defined by
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
*
|
||||
* 6. NULL_PTR: This macro is the value of a NULL pointer.
|
||||
*
|
||||
* In any ANSI/ISO C environment (and in many others as well),
|
||||
* this should be defined by
|
||||
*
|
||||
* #ifndef NULL_PTR
|
||||
* #define NULL_PTR 0
|
||||
* #endif
|
||||
*/
|
||||
|
||||
|
||||
/* All the various PKCS #11 types and #define'd values are in the
|
||||
* file pkcs11t.h. */
|
||||
#include "pkcs11t.h"
|
||||
|
||||
#define __PASTE(x,y) x##y
|
||||
|
||||
|
||||
/* packing defines */
|
||||
#include "pkcs11p.h"
|
||||
/* ==============================================================
|
||||
* Define the "extern" form of all the entry points.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_NEED_ARG_LIST 1
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
CK_DECLARE_FUNCTION(CK_RV, name)
|
||||
|
||||
/* pkcs11f.h has all the information about the PKCS #11
|
||||
* function prototypes. */
|
||||
#include "pkcs11f.h"
|
||||
|
||||
#undef CK_NEED_ARG_LIST
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
/* ==============================================================
|
||||
* Define the typedef form of all the entry points. That is, for
|
||||
* each PKCS #11 function C_XXX, define a type CK_C_XXX which is
|
||||
* a pointer to that kind of function.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_NEED_ARG_LIST 1
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
|
||||
|
||||
/* pkcs11f.h has all the information about the PKCS #11
|
||||
* function prototypes. */
|
||||
#include "pkcs11f.h"
|
||||
|
||||
#undef CK_NEED_ARG_LIST
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
/* ==============================================================
|
||||
* Define structed vector of entry points. A CK_FUNCTION_LIST
|
||||
* contains a CK_VERSION indicating a library's PKCS #11 version
|
||||
* and then a whole slew of function pointers to the routines in
|
||||
* the library. This type was declared, but not defined, in
|
||||
* pkcs11t.h.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
__PASTE(CK_,name) name;
|
||||
|
||||
struct CK_FUNCTION_LIST {
|
||||
|
||||
CK_VERSION version; /* PKCS #11 version */
|
||||
|
||||
/* Pile all the function pointers into the CK_FUNCTION_LIST. */
|
||||
/* pkcs11f.h has all the information about the PKCS #11
|
||||
* function prototypes. */
|
||||
#include "pkcs11f.h"
|
||||
|
||||
};
|
||||
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
#undef __PASTE
|
||||
|
||||
/* unpack */
|
||||
#include "pkcs11u.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,937 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* RSA Security INC.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
|
||||
* is granted provided that it is identified as "RSA Security In.c Public-Key
|
||||
* Cryptography Standards (PKCS)" in all material mentioning or referencing
|
||||
* this document.
|
||||
*/
|
||||
/* This function contains pretty much everything about all the */
|
||||
/* PKCS #11 function prototypes. Because this information is */
|
||||
/* used for more than just declaring function prototypes, the */
|
||||
/* order of the functions appearing herein is important, and */
|
||||
/* should not be altered. */
|
||||
|
||||
|
||||
|
||||
/* General-purpose */
|
||||
|
||||
/* C_Initialize initializes the PKCS #11 library. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Initialize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
|
||||
* cast to CK_C_INITIALIZE_ARGS_PTR
|
||||
* and dereferenced */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Finalize indicates that an application is done with the
|
||||
* PKCS #11 library. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Finalize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetInfo returns general information about PKCS #11. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_INFO_PTR pInfo /* location that receives information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetFunctionList returns the function list. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
|
||||
* function list */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Slot and token management */
|
||||
|
||||
/* C_GetSlotList obtains a list of slots in the system. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_BBOOL tokenPresent, /* only slots with tokens? */
|
||||
CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
|
||||
CK_ULONG_PTR pulCount /* receives number of slots */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetSlotInfo obtains information about a particular slot in
|
||||
* the system. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* the ID of the slot */
|
||||
CK_SLOT_INFO_PTR pInfo /* receives the slot information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetTokenInfo obtains information about a particular token
|
||||
* in the system. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_TOKEN_INFO_PTR pInfo /* receives the token information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetMechanismList obtains a list of mechanism types
|
||||
* supported by a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of token's slot */
|
||||
CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
|
||||
CK_ULONG_PTR pulCount /* gets # of mechs. */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetMechanismInfo obtains information about a particular
|
||||
* mechanism possibly supported by a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_MECHANISM_TYPE type, /* type of mechanism */
|
||||
CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_InitToken initializes a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_InitToken)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
|
||||
CK_ULONG ulPinLen, /* length in bytes of the PIN */
|
||||
CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_InitPIN initializes the normal user's PIN. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_InitPIN)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
|
||||
CK_ULONG ulPinLen /* length in bytes of the PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetPIN modifies the PIN of the user who is logged in. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetPIN)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
|
||||
CK_ULONG ulOldLen, /* length of the old PIN */
|
||||
CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
|
||||
CK_ULONG ulNewLen /* length of the new PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Session management */
|
||||
|
||||
/* C_OpenSession opens a session between an application and a
|
||||
* token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_OpenSession)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* the slot's ID */
|
||||
CK_FLAGS flags, /* from CK_SESSION_INFO */
|
||||
CK_VOID_PTR pApplication, /* passed to callback */
|
||||
CK_NOTIFY Notify, /* callback function */
|
||||
CK_SESSION_HANDLE_PTR phSession /* gets session handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CloseSession closes a session between an application and a
|
||||
* token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CloseSession)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CloseAllSessions closes all sessions with a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID /* the token's slot */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetSessionInfo obtains information about the session. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_SESSION_INFO_PTR pInfo /* receives session info */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetOperationState obtains the state of the cryptographic operation
|
||||
* in a session. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* gets state */
|
||||
CK_ULONG_PTR pulOperationStateLen /* gets state length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetOperationState restores the state of the cryptographic
|
||||
* operation in a session. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* holds state */
|
||||
CK_ULONG ulOperationStateLen, /* holds state length */
|
||||
CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
|
||||
CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Login logs a user into a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Login)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_USER_TYPE userType, /* the user type */
|
||||
CK_UTF8CHAR_PTR pPin, /* the user's PIN */
|
||||
CK_ULONG ulPinLen /* the length of the PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Logout logs a user out from a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Logout)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Object management */
|
||||
|
||||
/* C_CreateObject creates a new object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CreateObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CopyObject copies an object, creating a new object for the
|
||||
* copy. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CopyObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DestroyObject destroys an object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject /* the object's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetObjectSize gets the size of an object in bytes. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ULONG_PTR pulSize /* receives size of object */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetAttributeValue obtains the value of one or more object
|
||||
* attributes. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
|
||||
CK_ULONG ulCount /* attributes in template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetAttributeValue modifies the value of one or more object
|
||||
* attributes */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
|
||||
CK_ULONG ulCount /* attributes in template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjectsInit initializes a search for token and session
|
||||
* objects that match a template. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
|
||||
CK_ULONG ulCount /* attrs in search template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjects continues a search for token and session
|
||||
* objects that match a template, obtaining additional object
|
||||
* handles. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjects)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
|
||||
CK_ULONG ulMaxObjectCount, /* max handles to get */
|
||||
CK_ULONG_PTR pulObjectCount /* actual # returned */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjectsFinal finishes a search for token and session
|
||||
* objects. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Encryption and decryption */
|
||||
|
||||
/* C_EncryptInit initializes an encryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of encryption key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Encrypt encrypts single-part data. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Encrypt)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pData, /* the plaintext data */
|
||||
CK_ULONG ulDataLen, /* bytes of plaintext */
|
||||
CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_EncryptUpdate continues a multiple-part encryption
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext data len */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_EncryptFinal finishes a multiple-part encryption
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session handle */
|
||||
CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
|
||||
CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptInit initializes a decryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of decryption key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Decrypt decrypts encrypted data in a single part. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Decrypt)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedData, /* ciphertext */
|
||||
CK_ULONG ulEncryptedDataLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pData, /* gets plaintext */
|
||||
CK_ULONG_PTR pulDataLen /* gets p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptUpdate continues a multiple-part decryption
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* encrypted data */
|
||||
CK_ULONG ulEncryptedPartLen, /* input length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptFinal finishes a multiple-part decryption
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pLastPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulLastPartLen /* p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Message digesting */
|
||||
|
||||
/* C_DigestInit initializes a message-digesting operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Digest digests data in a single part. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Digest)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* data to be digested */
|
||||
CK_ULONG ulDataLen, /* bytes of data to digest */
|
||||
CK_BYTE_PTR pDigest, /* gets the message digest */
|
||||
CK_ULONG_PTR pulDigestLen /* gets digest length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestUpdate continues a multiple-part message-digesting
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* data to be digested */
|
||||
CK_ULONG ulPartLen /* bytes of data to be digested */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestKey continues a multi-part message-digesting
|
||||
* operation, by digesting the value of a secret key as part of
|
||||
* the data already digested. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hKey /* secret key to digest */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestFinal finishes a multiple-part message-digesting
|
||||
* operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pDigest, /* gets the message digest */
|
||||
CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Signing and MACing */
|
||||
|
||||
/* C_SignInit initializes a signature (private key encryption)
|
||||
* operation, where the signature is (will be) an appendix to
|
||||
* the data, and plaintext cannot be recovered from the
|
||||
*signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of signature key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Sign signs (encrypts with private key) data in a single
|
||||
* part, where the signature is (will be) an appendix to the
|
||||
* data, and plaintext cannot be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Sign)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* the data to sign */
|
||||
CK_ULONG ulDataLen, /* count of bytes to sign */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignUpdate continues a multiple-part signature operation,
|
||||
* where the signature is (will be) an appendix to the data,
|
||||
* and plaintext cannot be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* the data to sign */
|
||||
CK_ULONG ulPartLen /* count of bytes to sign */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignFinal finishes a multiple-part signature operation,
|
||||
* returning the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignRecoverInit initializes a signature operation, where
|
||||
* the data can be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of the signature key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignRecover signs data in a single operation, where the
|
||||
* data can be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignRecover)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* the data to sign */
|
||||
CK_ULONG ulDataLen, /* count of bytes to sign */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Verifying signatures and MACs */
|
||||
|
||||
/* C_VerifyInit initializes a verification operation, where the
|
||||
* signature is an appendix to the data, and plaintext cannot
|
||||
* cannot be recovered from the signature (e.g. DSA). */
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* verification key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Verify verifies a signature in a single-part operation,
|
||||
* where the signature is an appendix to the data, and plaintext
|
||||
* cannot be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Verify)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* signed data */
|
||||
CK_ULONG ulDataLen, /* length of signed data */
|
||||
CK_BYTE_PTR pSignature, /* signature */
|
||||
CK_ULONG ulSignatureLen /* signature length*/
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyUpdate continues a multiple-part verification
|
||||
* operation, where the signature is an appendix to the data,
|
||||
* and plaintext cannot be recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* signed data */
|
||||
CK_ULONG ulPartLen /* length of signed data */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyFinal finishes a multiple-part verification
|
||||
* operation, checking the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* signature to verify */
|
||||
CK_ULONG ulSignatureLen /* signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyRecoverInit initializes a signature verification
|
||||
* operation, where the data is recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* verification key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyRecover verifies a signature in a single-part
|
||||
* operation, where the data is recovered from the signature. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* signature to verify */
|
||||
CK_ULONG ulSignatureLen, /* signature length */
|
||||
CK_BYTE_PTR pData, /* gets signed data */
|
||||
CK_ULONG_PTR pulDataLen /* gets signed data len */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Dual-function cryptographic operations */
|
||||
|
||||
/* C_DigestEncryptUpdate continues a multiple-part digesting
|
||||
* and encryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext length */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptDigestUpdate continues a multiple-part decryption and
|
||||
* digesting operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
|
||||
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* gets plaintext len */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignEncryptUpdate continues a multiple-part signing and
|
||||
* encryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext length */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptVerifyUpdate continues a multiple-part decryption and
|
||||
* verify operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
|
||||
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* gets p-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Key management */
|
||||
|
||||
/* C_GenerateKey generates a secret key, creating a new key
|
||||
* object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key generation mech. */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
|
||||
CK_ULONG ulCount, /* # of attrs in template */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GenerateKeyPair generates a public-key/private-key pair,
|
||||
* creating new key objects. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session
|
||||
* handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key-gen
|
||||
* mech. */
|
||||
CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
|
||||
* for pub.
|
||||
* key */
|
||||
CK_ULONG ulPublicKeyAttributeCount, /* # pub.
|
||||
* attrs. */
|
||||
CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
|
||||
* for priv.
|
||||
* key */
|
||||
CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
|
||||
* attrs. */
|
||||
CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
|
||||
* key
|
||||
* handle */
|
||||
CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
|
||||
* priv. key
|
||||
* handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_WrapKey wraps (i.e., encrypts) a key. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_WrapKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
|
||||
CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
|
||||
CK_OBJECT_HANDLE hKey, /* key to be wrapped */
|
||||
CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
|
||||
CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
|
||||
* key object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
|
||||
CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
|
||||
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
|
||||
CK_ULONG ulWrappedKeyLen, /* wrapped key len */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
|
||||
CK_ULONG ulAttributeCount, /* template length */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DeriveKey derives a key from a base key, creating a new key
|
||||
* object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
|
||||
CK_OBJECT_HANDLE hBaseKey, /* base key */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
|
||||
CK_ULONG ulAttributeCount, /* template length */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Random number generation */
|
||||
|
||||
/* C_SeedRandom mixes additional seed material into the token's
|
||||
* random number generator. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSeed, /* the seed material */
|
||||
CK_ULONG ulSeedLen /* length of seed material */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GenerateRandom generates random data. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR RandomData, /* receives the random data */
|
||||
CK_ULONG ulRandomLen /* # of bytes to generate */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Parallel function management */
|
||||
|
||||
/* C_GetFunctionStatus is a legacy function; it obtains an
|
||||
* updated status of a function running in parallel with an
|
||||
* application. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CancelFunction is a legacy function; it cancels a function
|
||||
* running in parallel. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Functions added in for PKCS #11 Version 2.01 or later */
|
||||
|
||||
/* C_WaitForSlotEvent waits for a slot event (token insertion,
|
||||
* removal, etc.) to occur. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_FLAGS flags, /* blocking/nonblocking flag */
|
||||
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
|
||||
CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
|
||||
);
|
||||
#endif
|
||||
@@ -1,687 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* Internal data structures and functions used by pkcs11.c
|
||||
*/
|
||||
#ifndef _PKCS11I_H_
|
||||
#define _PKCS11I_H_ 1
|
||||
|
||||
#include "nssilock.h"
|
||||
#include "seccomon.h"
|
||||
#include "secoidt.h"
|
||||
#include "lowkeyti.h"
|
||||
#include "pkcs11t.h"
|
||||
|
||||
#include "sftkdbt.h"
|
||||
|
||||
|
||||
/*
|
||||
* Configuration Defines
|
||||
*
|
||||
* The following defines affect the space verse speed trade offs of
|
||||
* the PKCS #11 module. For the most part the current settings are optimized
|
||||
* for web servers, where we want faster speed and lower lock contention at
|
||||
* the expense of space.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The attribute allocation strategy is static allocation:
|
||||
* Attributes are pre-allocated as part of the session object and used from
|
||||
* the object array.
|
||||
*/
|
||||
#define MAX_OBJS_ATTRS 45 /* number of attributes to preallocate in
|
||||
* the object (must me the absolute max) */
|
||||
#define ATTR_SPACE 50 /* Maximum size of attribute data before extra
|
||||
* data needs to be allocated. This is set to
|
||||
* enough space to hold an SSL MASTER secret */
|
||||
|
||||
#define NSC_STRICT PR_FALSE /* forces the code to do strict template
|
||||
* matching when doing C_FindObject on token
|
||||
* objects. This will slow down search in
|
||||
* NSS. */
|
||||
/* default search block allocations and increments */
|
||||
#define NSC_CERT_BLOCK_SIZE 50
|
||||
#define NSC_SEARCH_BLOCK_SIZE 5
|
||||
#define NSC_SLOT_LIST_BLOCK_SIZE 10
|
||||
|
||||
#define NSC_FIPS_MODULE 1
|
||||
#define NSC_NON_FIPS_MODULE 0
|
||||
|
||||
/* these are data base storage hashes, not cryptographic hashes.. The define
|
||||
* the effective size of the various object hash tables */
|
||||
/* clients care more about memory usage than lookup performance on
|
||||
* cyrptographic objects. Clients also have less objects around to play with
|
||||
*
|
||||
* we eventually should make this configurable at runtime! Especially now that
|
||||
* NSS is a shared library.
|
||||
*/
|
||||
#define SPACE_ATTRIBUTE_HASH_SIZE 32
|
||||
#define SPACE_SESSION_OBJECT_HASH_SIZE 32
|
||||
#define SPACE_SESSION_HASH_SIZE 32
|
||||
#define TIME_ATTRIBUTE_HASH_SIZE 32
|
||||
#define TIME_SESSION_OBJECT_HASH_SIZE 1024
|
||||
#define TIME_SESSION_HASH_SIZE 1024
|
||||
#define MAX_OBJECT_LIST_SIZE 800
|
||||
/* how many objects to keep on the free list
|
||||
* before we start freeing them */
|
||||
#define MAX_KEY_LEN 256 /* maximum symmetric key length in bytes */
|
||||
|
||||
#define MULTIACCESS "multiaccess:"
|
||||
|
||||
/*
|
||||
* LOG2_BUCKETS_PER_SESSION_LOCK must be a prime number.
|
||||
* With SESSION_HASH_SIZE=1024, LOG2 can be 9, 5, 1, or 0.
|
||||
* With SESSION_HASH_SIZE=4096, LOG2 can be 11, 9, 5, 1, or 0.
|
||||
*
|
||||
* HASH_SIZE LOG2_BUCKETS_PER BUCKETS_PER_LOCK NUMBER_OF_BUCKETS
|
||||
* 1024 9 512 2
|
||||
* 1024 5 32 32
|
||||
* 1024 1 2 512
|
||||
* 1024 0 1 1024
|
||||
* 4096 11 2048 2
|
||||
* 4096 9 512 8
|
||||
* 4096 5 32 128
|
||||
* 4096 1 2 2048
|
||||
* 4096 0 1 4096
|
||||
*/
|
||||
#define LOG2_BUCKETS_PER_SESSION_LOCK 1
|
||||
#define BUCKETS_PER_SESSION_LOCK (1 << (LOG2_BUCKETS_PER_SESSION_LOCK))
|
||||
/* NOSPREAD sessionID to hash table index macro has been slower. */
|
||||
|
||||
/* define typedefs, double as forward declarations as well */
|
||||
typedef struct SFTKAttributeStr SFTKAttribute;
|
||||
typedef struct SFTKObjectListStr SFTKObjectList;
|
||||
typedef struct SFTKObjectFreeListStr SFTKObjectFreeList;
|
||||
typedef struct SFTKObjectListElementStr SFTKObjectListElement;
|
||||
typedef struct SFTKObjectStr SFTKObject;
|
||||
typedef struct SFTKSessionObjectStr SFTKSessionObject;
|
||||
typedef struct SFTKTokenObjectStr SFTKTokenObject;
|
||||
typedef struct SFTKSessionStr SFTKSession;
|
||||
typedef struct SFTKSlotStr SFTKSlot;
|
||||
typedef struct SFTKSessionContextStr SFTKSessionContext;
|
||||
typedef struct SFTKSearchResultsStr SFTKSearchResults;
|
||||
typedef struct SFTKHashVerifyInfoStr SFTKHashVerifyInfo;
|
||||
typedef struct SFTKHashSignInfoStr SFTKHashSignInfo;
|
||||
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
|
||||
|
||||
/* define function pointer typdefs for pointer tables */
|
||||
typedef void (*SFTKDestroy)(void *, PRBool);
|
||||
typedef void (*SFTKBegin)(void *);
|
||||
typedef SECStatus (*SFTKCipher)(void *,void *,unsigned int *,unsigned int,
|
||||
void *, unsigned int);
|
||||
typedef SECStatus (*SFTKVerify)(void *,void *,unsigned int,void *,unsigned int);
|
||||
typedef void (*SFTKHash)(void *,void *,unsigned int);
|
||||
typedef void (*SFTKEnd)(void *,void *,unsigned int *,unsigned int);
|
||||
typedef void (*SFTKFree)(void *);
|
||||
|
||||
/* Value to tell if an attribute is modifiable or not.
|
||||
* NEVER: attribute is only set on creation.
|
||||
* ONCOPY: attribute is set on creation and can only be changed on copy.
|
||||
* SENSITIVE: attribute can only be changed to TRUE.
|
||||
* ALWAYS: attribute can always be changed.
|
||||
*/
|
||||
typedef enum {
|
||||
SFTK_NEVER = 0,
|
||||
SFTK_ONCOPY = 1,
|
||||
SFTK_SENSITIVE = 2,
|
||||
SFTK_ALWAYS = 3
|
||||
} SFTKModifyType;
|
||||
|
||||
/*
|
||||
* Free Status Enum... tell us more information when we think we're
|
||||
* deleting an object.
|
||||
*/
|
||||
typedef enum {
|
||||
SFTK_DestroyFailure,
|
||||
SFTK_Destroyed,
|
||||
SFTK_Busy
|
||||
} SFTKFreeStatus;
|
||||
|
||||
/*
|
||||
* attribute values of an object.
|
||||
*/
|
||||
struct SFTKAttributeStr {
|
||||
SFTKAttribute *next;
|
||||
SFTKAttribute *prev;
|
||||
PRBool freeAttr;
|
||||
PRBool freeData;
|
||||
/*must be called handle to make sftkqueue_find work */
|
||||
CK_ATTRIBUTE_TYPE handle;
|
||||
CK_ATTRIBUTE attrib;
|
||||
unsigned char space[ATTR_SPACE];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* doubly link list of objects
|
||||
*/
|
||||
struct SFTKObjectListStr {
|
||||
SFTKObjectList *next;
|
||||
SFTKObjectList *prev;
|
||||
SFTKObject *parent;
|
||||
};
|
||||
|
||||
struct SFTKObjectFreeListStr {
|
||||
SFTKObject *head;
|
||||
PZLock *lock;
|
||||
int count;
|
||||
};
|
||||
|
||||
/*
|
||||
* PKCS 11 crypto object structure
|
||||
*/
|
||||
struct SFTKObjectStr {
|
||||
SFTKObject *next;
|
||||
SFTKObject *prev;
|
||||
CK_OBJECT_CLASS objclass;
|
||||
CK_OBJECT_HANDLE handle;
|
||||
int refCount;
|
||||
PZLock *refLock;
|
||||
SFTKSlot *slot;
|
||||
void *objectInfo;
|
||||
SFTKFree infoFree;
|
||||
};
|
||||
|
||||
struct SFTKTokenObjectStr {
|
||||
SFTKObject obj;
|
||||
SECItem dbKey;
|
||||
};
|
||||
|
||||
struct SFTKSessionObjectStr {
|
||||
SFTKObject obj;
|
||||
SFTKObjectList sessionList;
|
||||
PZLock *attributeLock;
|
||||
SFTKSession *session;
|
||||
PRBool wasDerived;
|
||||
int nextAttr;
|
||||
SFTKAttribute attrList[MAX_OBJS_ATTRS];
|
||||
PRBool optimizeSpace;
|
||||
unsigned int hashSize;
|
||||
SFTKAttribute *head[1];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct to deal with a temparary list of objects
|
||||
*/
|
||||
struct SFTKObjectListElementStr {
|
||||
SFTKObjectListElement *next;
|
||||
SFTKObject *object;
|
||||
};
|
||||
|
||||
/*
|
||||
* Area to hold Search results
|
||||
*/
|
||||
struct SFTKSearchResultsStr {
|
||||
CK_OBJECT_HANDLE *handles;
|
||||
int size;
|
||||
int index;
|
||||
int array_size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* the universal crypto/hash/sign/verify context structure
|
||||
*/
|
||||
typedef enum {
|
||||
SFTK_ENCRYPT,
|
||||
SFTK_DECRYPT,
|
||||
SFTK_HASH,
|
||||
SFTK_SIGN,
|
||||
SFTK_SIGN_RECOVER,
|
||||
SFTK_VERIFY,
|
||||
SFTK_VERIFY_RECOVER
|
||||
} SFTKContextType;
|
||||
|
||||
|
||||
#define SFTK_MAX_BLOCK_SIZE 16
|
||||
/* currently SHA512 is the biggest hash length */
|
||||
#define SFTK_MAX_MAC_LENGTH 64
|
||||
#define SFTK_INVALID_MAC_SIZE 0xffffffff
|
||||
|
||||
struct SFTKSessionContextStr {
|
||||
SFTKContextType type;
|
||||
PRBool multi; /* is multipart */
|
||||
PRBool doPad; /* use PKCS padding for block ciphers */
|
||||
unsigned int blockSize; /* blocksize for padding */
|
||||
unsigned int padDataLength; /* length of the valid data in padbuf */
|
||||
unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
|
||||
unsigned char macBuf[SFTK_MAX_BLOCK_SIZE];
|
||||
CK_ULONG macSize; /* size of a general block cipher mac*/
|
||||
void *cipherInfo;
|
||||
void *hashInfo;
|
||||
unsigned int cipherInfoLen;
|
||||
CK_MECHANISM_TYPE currentMech;
|
||||
SFTKCipher update;
|
||||
SFTKHash hashUpdate;
|
||||
SFTKEnd end;
|
||||
SFTKDestroy destroy;
|
||||
SFTKDestroy hashdestroy;
|
||||
SFTKVerify verify;
|
||||
unsigned int maxLen;
|
||||
SFTKObject *key;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sessions (have objects)
|
||||
*/
|
||||
struct SFTKSessionStr {
|
||||
SFTKSession *next;
|
||||
SFTKSession *prev;
|
||||
CK_SESSION_HANDLE handle;
|
||||
int refCount;
|
||||
PZLock *objectLock;
|
||||
int objectIDCount;
|
||||
CK_SESSION_INFO info;
|
||||
CK_NOTIFY notify;
|
||||
CK_VOID_PTR appData;
|
||||
SFTKSlot *slot;
|
||||
SFTKSearchResults *search;
|
||||
SFTKSessionContext *enc_context;
|
||||
SFTKSessionContext *hash_context;
|
||||
SFTKSessionContext *sign_context;
|
||||
SFTKObjectList *objects[1];
|
||||
};
|
||||
|
||||
/*
|
||||
* slots (have sessions and objects)
|
||||
*
|
||||
* The array of sessionLock's protect the session hash table (head[])
|
||||
* as well as the reference count of session objects in that bucket
|
||||
* (head[]->refCount), objectLock protects all elements of the slot's
|
||||
* object hash tables (sessObjHashTable[] and tokObjHashTable), and
|
||||
* sessionObjectHandleCount.
|
||||
* slotLock protects the remaining protected elements:
|
||||
* password, isLoggedIn, ssoLoggedIn, and sessionCount,
|
||||
* and pwCheckLock serializes the key database password checks in
|
||||
* NSC_SetPIN and NSC_Login.
|
||||
*
|
||||
* Each of the fields below has the following lifetime as commented
|
||||
* next to the fields:
|
||||
* invariant - This value is set when the slot is first created and
|
||||
* never changed until it is destroyed.
|
||||
* per load - This value is set when the slot is first created, or
|
||||
* when the slot is used to open another directory. Between open and close
|
||||
* this field does not change.
|
||||
* variable - This value changes through the normal process of slot operation.
|
||||
* - reset. The value of this variable is cleared during an open/close
|
||||
* cycles.
|
||||
* - preserved. The value of this variable is preserved over open/close
|
||||
* cycles.
|
||||
*/
|
||||
struct SFTKSlotStr {
|
||||
CK_SLOT_ID slotID; /* invariant */
|
||||
PZLock *slotLock; /* invariant */
|
||||
PZLock **sessionLock; /* invariant */
|
||||
unsigned int numSessionLocks; /* invariant */
|
||||
unsigned long sessionLockMask; /* invariant */
|
||||
PZLock *objectLock; /* invariant */
|
||||
PRLock *pwCheckLock; /* invariant */
|
||||
PRBool present; /* variable -set */
|
||||
PRBool hasTokens; /* per load */
|
||||
PRBool isLoggedIn; /* variable - reset */
|
||||
PRBool ssoLoggedIn; /* variable - reset */
|
||||
PRBool needLogin; /* per load */
|
||||
PRBool DB_loaded; /* per load */
|
||||
PRBool readOnly; /* per load */
|
||||
PRBool optimizeSpace; /* invariant */
|
||||
SFTKDBHandle *certDB; /* per load */
|
||||
SFTKDBHandle *keyDB; /* per load */
|
||||
int minimumPinLen; /* per load */
|
||||
PRInt32 sessionIDCount; /* atomically incremented */
|
||||
/* (preserved) */
|
||||
int sessionIDConflict; /* not protected by a lock */
|
||||
/* (preserved) */
|
||||
int sessionCount; /* variable - reset */
|
||||
PRInt32 rwSessionCount; /* set by atomic operations */
|
||||
/* (reset) */
|
||||
int sessionObjectHandleCount;/* variable - perserved */
|
||||
int index; /* invariant */
|
||||
PLHashTable *tokObjHashTable; /* invariant */
|
||||
SFTKObject **sessObjHashTable; /* variable - reset */
|
||||
unsigned int sessObjHashSize; /* invariant */
|
||||
SFTKSession **head; /* variable -reset */
|
||||
unsigned int sessHashSize; /* invariant */
|
||||
char tokDescription[33]; /* per load */
|
||||
char slotDescription[64]; /* invariant */
|
||||
};
|
||||
|
||||
/*
|
||||
* special joint operations Contexts
|
||||
*/
|
||||
struct SFTKHashVerifyInfoStr {
|
||||
SECOidTag hashOid;
|
||||
NSSLOWKEYPublicKey *key;
|
||||
};
|
||||
|
||||
struct SFTKHashSignInfoStr {
|
||||
SECOidTag hashOid;
|
||||
NSSLOWKEYPrivateKey *key;
|
||||
};
|
||||
|
||||
/* context for the Final SSLMAC message */
|
||||
struct SFTKSSLMACInfoStr {
|
||||
void *hashContext;
|
||||
SFTKBegin begin;
|
||||
SFTKHash update;
|
||||
SFTKEnd end;
|
||||
CK_ULONG macSize;
|
||||
int padSize;
|
||||
unsigned char key[MAX_KEY_LEN];
|
||||
unsigned int keySize;
|
||||
};
|
||||
|
||||
/*
|
||||
* session handle modifiers
|
||||
*/
|
||||
#define SFTK_SESSION_SLOT_MASK 0xff000000L
|
||||
|
||||
/*
|
||||
* object handle modifiers
|
||||
*/
|
||||
#define SFTK_TOKEN_MASK 0x80000000L
|
||||
#define SFTK_TOKEN_MAGIC 0x80000000L
|
||||
#define SFTK_TOKEN_TYPE_MASK 0x70000000L
|
||||
/* keydb (high bit == 0) */
|
||||
#define SFTK_TOKEN_TYPE_PRIV 0x10000000L
|
||||
#define SFTK_TOKEN_TYPE_PUB 0x20000000L
|
||||
#define SFTK_TOKEN_TYPE_KEY 0x30000000L
|
||||
/* certdb (high bit == 1) */
|
||||
#define SFTK_TOKEN_TYPE_TRUST 0x40000000L
|
||||
#define SFTK_TOKEN_TYPE_CRL 0x50000000L
|
||||
#define SFTK_TOKEN_TYPE_SMIME 0x60000000L
|
||||
#define SFTK_TOKEN_TYPE_CERT 0x70000000L
|
||||
|
||||
#define SFTK_TOKEN_KRL_HANDLE (SFTK_TOKEN_MAGIC|SFTK_TOKEN_TYPE_CRL|1)
|
||||
/* how big (in bytes) a password/pin we can deal with */
|
||||
#define SFTK_MAX_PIN 255
|
||||
/* minimum password/pin length (in Unicode characters) in FIPS mode */
|
||||
#define FIPS_MIN_PIN 7
|
||||
|
||||
/* slot ID's */
|
||||
#define NETSCAPE_SLOT_ID 1
|
||||
#define PRIVATE_KEY_SLOT_ID 2
|
||||
#define FIPS_SLOT_ID 3
|
||||
|
||||
/* slot helper macros */
|
||||
#define sftk_SlotFromSession(sp) ((sp)->slot)
|
||||
#define sftk_isToken(id) (((id) & SFTK_TOKEN_MASK) == SFTK_TOKEN_MAGIC)
|
||||
|
||||
/* the session hash multiplier (see bug 201081) */
|
||||
#define SHMULTIPLIER 1791398085
|
||||
|
||||
/* queueing helper macros */
|
||||
#define sftk_hash(value,size) \
|
||||
((PRUint32)((value) * SHMULTIPLIER) & (size-1))
|
||||
#define sftkqueue_add(element,id,head,hash_size) \
|
||||
{ int tmp = sftk_hash(id,hash_size); \
|
||||
(element)->next = (head)[tmp]; \
|
||||
(element)->prev = NULL; \
|
||||
if ((head)[tmp]) (head)[tmp]->prev = (element); \
|
||||
(head)[tmp] = (element); }
|
||||
#define sftkqueue_find(element,id,head,hash_size) \
|
||||
for( (element) = (head)[sftk_hash(id,hash_size)]; (element) != NULL; \
|
||||
(element) = (element)->next) { \
|
||||
if ((element)->handle == (id)) { break; } }
|
||||
#define sftkqueue_is_queued(element,id,head,hash_size) \
|
||||
( ((element)->next) || ((element)->prev) || \
|
||||
((head)[sftk_hash(id,hash_size)] == (element)) )
|
||||
#define sftkqueue_delete(element,id,head,hash_size) \
|
||||
if ((element)->next) (element)->next->prev = (element)->prev; \
|
||||
if ((element)->prev) (element)->prev->next = (element)->next; \
|
||||
else (head)[sftk_hash(id,hash_size)] = ((element)->next); \
|
||||
(element)->next = NULL; \
|
||||
(element)->prev = NULL; \
|
||||
|
||||
#define sftkqueue_init_element(element) \
|
||||
(element)->prev = NULL;
|
||||
|
||||
#define sftkqueue_add2(element, id, index, head) \
|
||||
{ \
|
||||
(element)->next = (head)[index]; \
|
||||
if ((head)[index]) \
|
||||
(head)[index]->prev = (element); \
|
||||
(head)[index] = (element); \
|
||||
}
|
||||
|
||||
#define sftkqueue_find2(element, id, index, head) \
|
||||
for ( (element) = (head)[index]; \
|
||||
(element) != NULL; \
|
||||
(element) = (element)->next) { \
|
||||
if ((element)->handle == (id)) { break; } \
|
||||
}
|
||||
|
||||
#define sftkqueue_delete2(element, id, index, head) \
|
||||
if ((element)->next) (element)->next->prev = (element)->prev; \
|
||||
if ((element)->prev) (element)->prev->next = (element)->next; \
|
||||
else (head)[index] = ((element)->next);
|
||||
|
||||
#define sftkqueue_clear_deleted_element(element) \
|
||||
(element)->next = NULL; \
|
||||
(element)->prev = NULL; \
|
||||
|
||||
|
||||
/* sessionID (handle) is used to determine session lock bucket */
|
||||
#ifdef NOSPREAD
|
||||
/* NOSPREAD: (ID>>L2LPB) & (perbucket-1) */
|
||||
#define SFTK_SESSION_LOCK(slot,handle) \
|
||||
((slot)->sessionLock[((handle) >> LOG2_BUCKETS_PER_SESSION_LOCK) \
|
||||
& (slot)->sessionLockMask])
|
||||
#else
|
||||
/* SPREAD: ID & (perbucket-1) */
|
||||
#define SFTK_SESSION_LOCK(slot,handle) \
|
||||
((slot)->sessionLock[(handle) & (slot)->sessionLockMask])
|
||||
#endif
|
||||
|
||||
/* expand an attribute & secitem structures out */
|
||||
#define sftk_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
|
||||
#define sftk_item_expand(ip) (ip)->data,(ip)->len
|
||||
|
||||
typedef struct sftk_token_parametersStr {
|
||||
CK_SLOT_ID slotID;
|
||||
char *configdir;
|
||||
char *certPrefix;
|
||||
char *keyPrefix;
|
||||
char *tokdes;
|
||||
char *slotdes;
|
||||
int minPW;
|
||||
PRBool readOnly;
|
||||
PRBool noCertDB;
|
||||
PRBool noKeyDB;
|
||||
PRBool forceOpen;
|
||||
PRBool pwRequired;
|
||||
PRBool optimizeSpace;
|
||||
} sftk_token_parameters;
|
||||
|
||||
typedef struct sftk_parametersStr {
|
||||
char *configdir;
|
||||
char *secmodName;
|
||||
char *man;
|
||||
char *libdes;
|
||||
PRBool readOnly;
|
||||
PRBool noModDB;
|
||||
PRBool noCertDB;
|
||||
PRBool forceOpen;
|
||||
PRBool pwRequired;
|
||||
PRBool optimizeSpace;
|
||||
sftk_token_parameters *tokens;
|
||||
int token_count;
|
||||
} sftk_parameters;
|
||||
|
||||
|
||||
/* machine dependent path stuff used by dbinit.c and pk11db.c */
|
||||
#ifdef macintosh
|
||||
#define PATH_SEPARATOR ":"
|
||||
#define SECMOD_DB "Security Modules"
|
||||
#define CERT_DB_FMT "%sCertificates%s"
|
||||
#define KEY_DB_FMT "%sKey Database%s"
|
||||
#else
|
||||
#define PATH_SEPARATOR "/"
|
||||
#define SECMOD_DB "secmod.db"
|
||||
#define CERT_DB_FMT "%scert%s.db"
|
||||
#define KEY_DB_FMT "%skey%s.db"
|
||||
#endif
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/* shared functions between pkcs11.c and fipstokn.c */
|
||||
extern PRBool nsf_init;
|
||||
extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
|
||||
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
|
||||
extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
|
||||
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
|
||||
|
||||
/* slot initialization, reinit, shutdown and destruction */
|
||||
extern CK_RV SFTK_SlotInit(char *configdir,
|
||||
sftk_token_parameters *params, int moduleIndex);
|
||||
extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
|
||||
sftk_token_parameters *params, int moduleIndex);
|
||||
extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
|
||||
extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
|
||||
|
||||
|
||||
/* internal utility functions used by pkcs11.c */
|
||||
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
|
||||
CK_ATTRIBUTE_TYPE type);
|
||||
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
|
||||
extern CK_RV sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
|
||||
void *valPtr,
|
||||
CK_ULONG length);
|
||||
extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
|
||||
SFTKObject *object, CK_ATTRIBUTE_TYPE type);
|
||||
extern unsigned int sftk_GetLengthInBits(unsigned char *buf,
|
||||
unsigned int bufLen);
|
||||
extern CK_RV sftk_ConstrainAttribute(SFTKObject *object,
|
||||
CK_ATTRIBUTE_TYPE type, int minLength, int maxLength, int minMultiple);
|
||||
extern PRBool sftk_hasAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
|
||||
extern PRBool sftk_isTrue(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
|
||||
extern void sftk_DeleteAttributeType(SFTKObject *object,
|
||||
CK_ATTRIBUTE_TYPE type);
|
||||
extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
|
||||
SFTKObject *object, CK_ATTRIBUTE_TYPE type);
|
||||
extern CK_RV sftk_Attribute2SSecItem(PLArenaPool *arena, SECItem *item,
|
||||
SFTKObject *object,
|
||||
CK_ATTRIBUTE_TYPE type);
|
||||
extern SFTKModifyType sftk_modifyType(CK_ATTRIBUTE_TYPE type,
|
||||
CK_OBJECT_CLASS inClass);
|
||||
extern PRBool sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
|
||||
extern char *sftk_getString(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
|
||||
extern void sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type);
|
||||
extern CK_RV sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
|
||||
CK_ULONG *longData);
|
||||
extern CK_RV sftk_forceAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
|
||||
void *value, unsigned int len);
|
||||
extern CK_RV sftk_defaultAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
|
||||
void *value, unsigned int len);
|
||||
extern unsigned int sftk_MapTrust(CK_TRUST trust, PRBool clientAuth);
|
||||
|
||||
extern SFTKObject *sftk_NewObject(SFTKSlot *slot);
|
||||
extern CK_RV sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject);
|
||||
extern SFTKFreeStatus sftk_FreeObject(SFTKObject *object);
|
||||
extern CK_RV sftk_DeleteObject(SFTKSession *session, SFTKObject *object);
|
||||
extern void sftk_ReferenceObject(SFTKObject *object);
|
||||
extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle,
|
||||
SFTKSession *session);
|
||||
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object);
|
||||
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object);
|
||||
/* clear out all the existing object ID to database key mappings.
|
||||
* used to reinit a token */
|
||||
extern CK_RV SFTK_ClearTokenKeyHashTable(SFTKSlot *slot);
|
||||
|
||||
extern CK_RV sftk_searchObjectList(SFTKSearchResults *search,
|
||||
SFTKObject **head, unsigned int size,
|
||||
PZLock *lock, CK_ATTRIBUTE_PTR inTemplate,
|
||||
int count, PRBool isLoggedIn);
|
||||
extern SFTKObjectListElement *sftk_FreeObjectListElement(
|
||||
SFTKObjectListElement *objectList);
|
||||
extern void sftk_FreeObjectList(SFTKObjectListElement *objectList);
|
||||
extern void sftk_FreeSearch(SFTKSearchResults *search);
|
||||
extern CK_RV sftk_handleObject(SFTKObject *object, SFTKSession *session);
|
||||
|
||||
extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all);
|
||||
extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle);
|
||||
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
|
||||
extern void sftk_FreeSession(SFTKSession *session);
|
||||
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
|
||||
CK_VOID_PTR pApplication, CK_FLAGS flags);
|
||||
extern void sftk_update_state(SFTKSlot *slot,SFTKSession *session);
|
||||
extern void sftk_update_all_states(SFTKSlot *slot);
|
||||
extern void sftk_FreeContext(SFTKSessionContext *context);
|
||||
extern void sftk_InitFreeLists(void);
|
||||
extern void sftk_CleanupFreeLists(void);
|
||||
|
||||
extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
|
||||
CK_KEY_TYPE key_type, CK_RV *crvp);
|
||||
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
|
||||
CK_KEY_TYPE key_type, CK_RV *crvp);
|
||||
extern void sftk_FormatDESKey(unsigned char *key, int length);
|
||||
extern PRBool sftk_CheckDESKey(unsigned char *key);
|
||||
extern PRBool sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type);
|
||||
|
||||
/* mechanism allows this operation */
|
||||
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
|
||||
|
||||
/* helper function which calls nsslowkey_FindKeyByPublicKey after safely
|
||||
* acquiring a reference to the keydb from the slot */
|
||||
NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey);
|
||||
|
||||
/*
|
||||
* narrow objects
|
||||
*/
|
||||
SFTKSessionObject * sftk_narrowToSessionObject(SFTKObject *);
|
||||
SFTKTokenObject * sftk_narrowToTokenObject(SFTKObject *);
|
||||
|
||||
/*
|
||||
* token object utilities
|
||||
*/
|
||||
void sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle);
|
||||
PRBool sftk_poisonHandle(SFTKSlot *slot, SECItem *dbkey,
|
||||
CK_OBJECT_HANDLE handle);
|
||||
SFTKObject * sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey,
|
||||
CK_OBJECT_HANDLE handle);
|
||||
SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so);
|
||||
|
||||
/****************************************
|
||||
* implement TLS Pseudo Random Function (PRF)
|
||||
*/
|
||||
|
||||
extern CK_RV
|
||||
sftk_TLSPRFInit(SFTKSessionContext *context,
|
||||
SFTKObject * key,
|
||||
CK_KEY_TYPE key_type);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _PKCS11I_H_ */
|
||||
@@ -1,281 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Stephen Henson <stephen.henson@gemplus.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _PKCS11N_H_
|
||||
#define _PKCS11N_H_
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.15.22.1 $ $Date: 2007-05-17 01:08:18 $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* pkcs11n.h
|
||||
*
|
||||
* This file contains the NSS-specific type definitions for Cryptoki
|
||||
* (PKCS#11).
|
||||
*/
|
||||
|
||||
/*
|
||||
* NSSCK_VENDOR_NSS
|
||||
*
|
||||
* Cryptoki reserves the high half of all the number spaces for
|
||||
* vendor-defined use. I'd like to keep all of our NSS-
|
||||
* specific values together, but not in the oh-so-obvious
|
||||
* 0x80000001, 0x80000002, etc. area. So I've picked an offset,
|
||||
* and constructed values for the beginnings of our spaces.
|
||||
*
|
||||
* Note that some "historical" Netscape values don't fall within
|
||||
* this range.
|
||||
*/
|
||||
#define NSSCK_VENDOR_NSS 0x4E534350 /* NSCP */
|
||||
|
||||
/*
|
||||
* NSS-defined object classes
|
||||
*
|
||||
*/
|
||||
#define CKO_NSS (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKO_NSS_CRL (CKO_NSS + 1)
|
||||
#define CKO_NSS_SMIME (CKO_NSS + 2)
|
||||
#define CKO_NSS_TRUST (CKO_NSS + 3)
|
||||
#define CKO_NSS_BUILTIN_ROOT_LIST (CKO_NSS + 4)
|
||||
#define CKO_NSS_NEWSLOT (CKO_NSS + 5)
|
||||
#define CKO_NSS_DELSLOT (CKO_NSS + 6)
|
||||
|
||||
|
||||
/*
|
||||
* NSS-defined key types
|
||||
*
|
||||
*/
|
||||
#define CKK_NSS (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKK_NSS_PKCS8 (CKK_NSS + 1)
|
||||
/*
|
||||
* NSS-defined certificate types
|
||||
*
|
||||
*/
|
||||
#define CKC_NSS (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
/*
|
||||
* NSS-defined object attributes
|
||||
*
|
||||
*/
|
||||
#define CKA_NSS (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKA_NSS_URL (CKA_NSS + 1)
|
||||
#define CKA_NSS_EMAIL (CKA_NSS + 2)
|
||||
#define CKA_NSS_SMIME_INFO (CKA_NSS + 3)
|
||||
#define CKA_NSS_SMIME_TIMESTAMP (CKA_NSS + 4)
|
||||
#define CKA_NSS_PKCS8_SALT (CKA_NSS + 5)
|
||||
#define CKA_NSS_PASSWORD_CHECK (CKA_NSS + 6)
|
||||
#define CKA_NSS_EXPIRES (CKA_NSS + 7)
|
||||
#define CKA_NSS_KRL (CKA_NSS + 8)
|
||||
|
||||
#define CKA_NSS_PQG_COUNTER (CKA_NSS + 20)
|
||||
#define CKA_NSS_PQG_SEED (CKA_NSS + 21)
|
||||
#define CKA_NSS_PQG_H (CKA_NSS + 22)
|
||||
#define CKA_NSS_PQG_SEED_BITS (CKA_NSS + 23)
|
||||
#define CKA_NSS_MODULE_SPEC (CKA_NSS + 24)
|
||||
#define CKA_NSS_OVERRIDE_EXTENSIONS (CKA_NSS + 25)
|
||||
|
||||
/*
|
||||
* Trust attributes:
|
||||
*
|
||||
* If trust goes standard, these probably will too. So I'll
|
||||
* put them all in one place.
|
||||
*/
|
||||
|
||||
#define CKA_TRUST (CKA_NSS + 0x2000)
|
||||
|
||||
/* "Usage" key information */
|
||||
#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1)
|
||||
#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2)
|
||||
#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3)
|
||||
#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4)
|
||||
#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5)
|
||||
#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6)
|
||||
#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7)
|
||||
|
||||
/* "Purpose" trust information */
|
||||
#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8)
|
||||
#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9)
|
||||
#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10)
|
||||
#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11)
|
||||
#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12)
|
||||
#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13)
|
||||
#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14)
|
||||
#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15)
|
||||
#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16)
|
||||
|
||||
#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100)
|
||||
#define CKA_CERT_MD5_HASH (CKA_TRUST + 101)
|
||||
|
||||
/* NSS trust stuff */
|
||||
/* XXX fgmr new ones here-- step-up, etc. */
|
||||
|
||||
/* HISTORICAL: define used to pass in the database key for DSA private keys */
|
||||
#define CKA_NETSCAPE_DB 0xD5A0DB00L
|
||||
#define CKA_NETSCAPE_TRUST 0x80000001L
|
||||
|
||||
/*
|
||||
* NSS-defined crypto mechanisms
|
||||
*
|
||||
*/
|
||||
#define CKM_NSS (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKM_NSS_AES_KEY_WRAP (CKM_NSS + 1)
|
||||
#define CKM_NSS_AES_KEY_WRAP_PAD (CKM_NSS + 2)
|
||||
|
||||
/*
|
||||
* HISTORICAL:
|
||||
* Do not attempt to use these. They are only used by NETSCAPE's internal
|
||||
* PKCS #11 interface. Most of these are place holders for other mechanism
|
||||
* and will change in the future.
|
||||
*/
|
||||
#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L
|
||||
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L
|
||||
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL
|
||||
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL
|
||||
|
||||
#define CKM_TLS_PRF_GENERAL 0x80000373L
|
||||
|
||||
/*
|
||||
* NSS-defined return values
|
||||
*
|
||||
*/
|
||||
#define CKR_NSS (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1)
|
||||
#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2)
|
||||
|
||||
/*
|
||||
* Trust info
|
||||
*
|
||||
* This isn't part of the Cryptoki standard (yet), so I'm putting
|
||||
* all the definitions here. Some of this would move to nssckt.h
|
||||
* if trust info were made part of the standard. In view of this
|
||||
* possibility, I'm putting my (NSS) values in the NSS
|
||||
* vendor space, like everything else.
|
||||
*/
|
||||
|
||||
typedef CK_ULONG CK_TRUST;
|
||||
|
||||
/* The following trust types are defined: */
|
||||
#define CKT_VENDOR_DEFINED 0x80000000
|
||||
|
||||
#define CKT_NSS (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
/* If trust goes standard, these'll probably drop out of vendor space. */
|
||||
#define CKT_NSS_TRUSTED (CKT_NSS + 1)
|
||||
#define CKT_NSS_TRUSTED_DELEGATOR (CKT_NSS + 2)
|
||||
#define CKT_NSS_UNTRUSTED (CKT_NSS + 3)
|
||||
#define CKT_NSS_MUST_VERIFY (CKT_NSS + 4)
|
||||
#define CKT_NSS_TRUST_UNKNOWN (CKT_NSS + 5) /* default */
|
||||
|
||||
/*
|
||||
* These may well remain NSS-specific; I'm only using them
|
||||
* to cache resolution data.
|
||||
*/
|
||||
#define CKT_NSS_VALID (CKT_NSS + 10)
|
||||
#define CKT_NSS_VALID_DELEGATOR (CKT_NSS + 11)
|
||||
|
||||
/* don't leave old programs in a lurch just yet, give them the old NETSCAPE
|
||||
* synonym */
|
||||
#define CKO_NETSCAPE_CRL CKO_NSS_CRL
|
||||
#define CKO_NETSCAPE_SMIME CKO_NSS_SMIME
|
||||
#define CKO_NETSCAPE_TRUST CKO_NSS_TRUST
|
||||
#define CKO_NETSCAPE_BUILTIN_ROOT_LIST CKO_NSS_BUILTIN_ROOT_LIST
|
||||
#define CKO_NETSCAPE_NEWSLOT CKO_NSS_NEWSLOT
|
||||
#define CKO_NETSCAPE_DELSLOT CKO_NSS_DELSLOT
|
||||
#define CKK_NETSCAPE_PKCS8 CKK_NSS_PKCS8
|
||||
#define CKA_NETSCAPE_URL CKA_NSS_URL
|
||||
#define CKA_NETSCAPE_EMAIL CKA_NSS_EMAIL
|
||||
#define CKA_NETSCAPE_SMIME_INFO CKA_NSS_SMIME_INFO
|
||||
#define CKA_NETSCAPE_SMIME_TIMESTAMP CKA_NSS_SMIME_TIMESTAMP
|
||||
#define CKA_NETSCAPE_PKCS8_SALT CKA_NSS_PKCS8_SALT
|
||||
#define CKA_NETSCAPE_PASSWORD_CHECK CKA_NSS_PASSWORD_CHECK
|
||||
#define CKA_NETSCAPE_EXPIRES CKA_NSS_EXPIRES
|
||||
#define CKA_NETSCAPE_KRL CKA_NSS_KRL
|
||||
#define CKA_NETSCAPE_PQG_COUNTER CKA_NSS_PQG_COUNTER
|
||||
#define CKA_NETSCAPE_PQG_SEED CKA_NSS_PQG_SEED
|
||||
#define CKA_NETSCAPE_PQG_H CKA_NSS_PQG_H
|
||||
#define CKA_NETSCAPE_PQG_SEED_BITS CKA_NSS_PQG_SEED_BITS
|
||||
#define CKA_NETSCAPE_MODULE_SPEC CKA_NSS_MODULE_SPEC
|
||||
#define CKM_NETSCAPE_AES_KEY_WRAP CKM_NSS_AES_KEY_WRAP
|
||||
#define CKM_NETSCAPE_AES_KEY_WRAP_PAD CKM_NSS_AES_KEY_WRAP_PAD
|
||||
#define CKR_NETSCAPE_CERTDB_FAILED CKR_NSS_CERTDB_FAILED
|
||||
#define CKR_NETSCAPE_KEYDB_FAILED CKR_NSS_KEYDB_FAILED
|
||||
#define CKT_NETSCAPE_TRUSTED CKT_NSS_TRUSTED
|
||||
#define CKT_NETSCAPE_TRUSTED_DELEGATOR CKT_NSS_TRUSTED_DELEGATOR
|
||||
#define CKT_NETSCAPE_UNTRUSTED CKT_NSS_UNTRUSTED
|
||||
#define CKT_NETSCAPE_MUST_VERIFY CKT_NSS_MUST_VERIFY
|
||||
#define CKT_NETSCAPE_TRUST_UNKNOWN CKT_NSS_TRUST_UNKNOWN
|
||||
#define CKT_NETSCAPE_VALID CKT_NSS_VALID
|
||||
#define CKT_NETSCAPE_VALID_DELEGATOR CKT_NSS_VALID_DELEGATOR
|
||||
|
||||
/*
|
||||
* These are not really PKCS #11 values specifically. They are the 'loadable'
|
||||
* module spec NSS uses. The are available for others to use as well, but not
|
||||
* part of the formal PKCS #11 spec.
|
||||
*
|
||||
* The function 'FIND' returns an array of PKCS #11 initialization strings
|
||||
* The function 'ADD' takes a PKCS #11 initialization string and stores it.
|
||||
* The function 'DEL' takes a 'name= library=' value and deletes the associated
|
||||
* string.
|
||||
* The function 'RELEASE' frees the array returned by 'FIND'
|
||||
*/
|
||||
#define SECMOD_MODULE_DB_FUNCTION_FIND 0
|
||||
#define SECMOD_MODULE_DB_FUNCTION_ADD 1
|
||||
#define SECMOD_MODULE_DB_FUNCTION_DEL 2
|
||||
#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3
|
||||
typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function,
|
||||
char *parameters, void *moduleSpec);
|
||||
|
||||
/* softoken slot ID's */
|
||||
#define SFTK_MIN_USER_SLOT_ID 4
|
||||
#define SFTK_MAX_USER_SLOT_ID 100
|
||||
#define SFTK_MIN_FIPS_USER_SLOT_ID 101
|
||||
#define SFTK_MAX_FIPS_USER_SLOT_ID 127
|
||||
|
||||
|
||||
#endif /* _PKCS11N_H_ */
|
||||
@@ -1,52 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Red Hat, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _PKCS11NI_H_
|
||||
#define _PKCS11NI_H_
|
||||
|
||||
/*
|
||||
* pkcs11ni.h
|
||||
*
|
||||
* This file contains softoken private exports for NSS
|
||||
*/
|
||||
|
||||
/* softoken slot ID's */
|
||||
#define SFTK_MIN_USER_SLOT_ID 4
|
||||
#define SFTK_MAX_USER_SLOT_ID 100
|
||||
#define SFTK_MIN_FIPS_USER_SLOT_ID 101
|
||||
#define SFTK_MAX_FIPS_USER_SLOT_ID 127
|
||||
|
||||
|
||||
#endif /* _PKCS11NI_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user