Bug Summary

File:root/firefox-clang/security/nss/lib/softoken/sdb.c
Warning:line 1638, column 5
Value stored to 'sqlerr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name sdb.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D SOFTOKEN_LIB_NAME="libsoftokn3.so" -D SHLIB_VERSION="3" -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/lib/softoken -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/security/nss/lib/softoken/sdb.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4/*
5 * This file implements PKCS 11 on top of our existing security modules
6 *
7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8 * This implementation has two slots:
9 * slot 1 is our generic crypto support. It does not require login.
10 * It supports Public Key ops, and all they bulk ciphers and hashes.
11 * It can also support Private Key ops for imported Private keys. It does
12 * not have any token storage.
13 * slot 2 is our private key support. It requires a login before use. It
14 * can store Private Keys and Certs as token objects. Currently only private
15 * keys and their associated Certificates are saved on the token.
16 *
17 * In this implementation, session objects are only visible to the session
18 * that created or generated them.
19 */
20
21#include "sdb.h"
22#include "pkcs11t.h"
23#include "seccomon.h"
24#include <sqlite3.h>
25#include "prthread.h"
26#include "prio.h"
27#include <stdio.h>
28#include <limits.h>
29#include "secport.h"
30#include "prmon.h"
31#include "prenv.h"
32#include "prprf.h"
33#include "prsystem.h" /* for PR_GetDirectorySeparator() */
34#include <sys/stat.h>
35#if defined(_WIN32)
36#include <io.h>
37#include <windows.h>
38#elif defined(XP_UNIX1)
39#include <unistd.h>
40#endif
41#if defined(LINUX1) && !defined(ANDROID)
42#include <linux1/magic.h>
43#include <sys/vfs.h>
44#endif
45#include "utilpars.h"
46
47#ifdef SQLITE_UNSAFE_THREADS
48#include "prlock.h"
49/*
50 * SQLite can be compiled to be thread safe or not.
51 * turn on SQLITE_UNSAFE_THREADS if the OS does not support
52 * a thread safe version of sqlite.
53 */
54static PRLock *sqlite_lock = NULL((void*)0);
55
56#define LOCK_SQLITE() PR_Lock(sqlite_lock);
57#define UNLOCK_SQLITE() PR_Unlock(sqlite_lock);
58#else
59#define LOCK_SQLITE()
60#define UNLOCK_SQLITE()
61#endif
62
63typedef enum {
64 SDB_CERT = 1,
65 SDB_KEY = 2
66} sdbDataType;
67
68/*
69 * defines controlling how long we wait to acquire locks.
70 *
71 * SDB_SQLITE_BUSY_TIMEOUT specifies how long (in milliseconds)
72 * sqlite will wait on lock. If that timeout expires, sqlite will
73 * return SQLITE_BUSY.
74 * SDB_BUSY_RETRY_TIME specifies how many seconds the sdb_ code waits
75 * after receiving a busy before retrying.
76 * SDB_MAX_BUSY_RETRIES specifies how many times the sdb_ will retry on
77 * a busy condition.
78 *
79 * SDB_SQLITE_BUSY_TIMEOUT affects all opertions, both manual
80 * (prepare/step/reset/finalize) and automatic (sqlite3_exec()).
81 * SDB_BUSY_RETRY_TIME and SDB_MAX_BUSY_RETRIES only affect manual operations
82 *
83 * total wait time for automatic operations:
84 * 1 second (SDB_SQLITE_BUSY_TIMEOUT/1000).
85 * total wait time for manual operations:
86 * (1 second + SDB_BUSY_RETRY_TIME) * 30 = 30 seconds.
87 * (SDB_SQLITE_BUSY_TIMEOUT/1000 + SDB_BUSY_RETRY_TIME)*SDB_MAX_BUSY_RETRIES
88 */
89#define SDB_SQLITE_BUSY_TIMEOUT1000 1000 /* milliseconds */
90#define SDB_BUSY_RETRY_TIME5 5 /* 'ticks', varies by platforms */
91#define SDB_MAX_BUSY_RETRIES30 30
92
93/*
94 * known attributes
95 */
96// clang-format off
97const CK_ATTRIBUTE_TYPE sftkdb_known_attributes[] = {
98 CKA_CLASS0x00000000UL, CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_LABEL0x00000003UL, CKA_UNIQUE_ID0x00000004UL,
99 CKA_APPLICATION0x00000010UL, CKA_VALUE0x00000011UL, CKA_OBJECT_ID0x00000012UL, CKA_CERTIFICATE_TYPE0x00000080UL, CKA_ISSUER0x00000081UL,
100 CKA_SERIAL_NUMBER0x00000082UL, CKA_AC_ISSUER0x00000083UL, CKA_OWNER0x00000084UL, CKA_ATTR_TYPES0x00000085UL, CKA_TRUSTED0x00000086UL,
101 CKA_CERTIFICATE_CATEGORY0x00000087UL, CKA_JAVA_MIDP_SECURITY_DOMAIN0x00000088UL, CKA_URL0x00000089UL,
102 CKA_HASH_OF_SUBJECT_PUBLIC_KEY0x0000008AUL, CKA_HASH_OF_ISSUER_PUBLIC_KEY0x0000008BUL,
103 CKA_NAME_HASH_ALGORITHM0x0000008cUL, CKA_CHECK_VALUE0x00000090UL, CKA_KEY_TYPE0x00000100UL, CKA_SUBJECT0x00000101UL,
104 CKA_ID0x00000102UL, CKA_SENSITIVE0x00000103UL, CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL,
105 CKA_SIGN0x00000108UL, CKA_SIGN_RECOVER0x00000109UL, CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, CKA_DERIVE0x0000010CUL,
106 CKA_START_DATE0x00000110UL, CKA_END_DATE0x00000111UL, CKA_MODULUS0x00000120UL, CKA_MODULUS_BITS0x00000121UL,
107 CKA_PUBLIC_EXPONENT0x00000122UL, CKA_PRIVATE_EXPONENT0x00000123UL, CKA_PRIME_10x00000124UL, CKA_PRIME_20x00000125UL,
108 CKA_EXPONENT_10x00000126UL, CKA_EXPONENT_20x00000127UL, CKA_COEFFICIENT0x00000128UL, CKA_PUBLIC_KEY_INFO0x00000129UL,
109 CKA_PRIME0x00000130UL, CKA_SUBPRIME0x00000131UL, CKA_BASE0x00000132UL, CKA_PRIME_BITS0x00000133UL, CKA_SUB_PRIME_BITS0x00000134UL,
110 CKA_VALUE_BITS0x00000160UL, CKA_VALUE_LEN0x00000161UL, CKA_EXTRACTABLE0x00000162UL, CKA_LOCAL0x00000163UL,
111 CKA_NEVER_EXTRACTABLE0x00000164UL, CKA_ALWAYS_SENSITIVE0x00000165UL, CKA_KEY_GEN_MECHANISM0x00000166UL,
112 CKA_MODIFIABLE0x00000170UL, CKA_COPYABLE0x00000171UL, CKA_DESTROYABLE0x00000172UL, CKA_EC_PARAMS0x00000180UL, CKA_EC_POINT0x00000181UL,
113 CKA_SECONDARY_AUTH0x00000200UL, CKA_AUTH_PIN_FLAGS0x00000201UL, CKA_ALWAYS_AUTHENTICATE0x00000202UL,
114 CKA_WRAP_WITH_TRUSTED0x00000210UL, CKA_WRAP_TEMPLATE(0x40000000UL | 0x00000211UL), CKA_UNWRAP_TEMPLATE(0x40000000UL | 0x00000212UL),
115 CKA_DERIVE_TEMPLATE(0x40000000UL | 0x00000213UL), CKA_OTP_FORMAT0x00000220UL, CKA_OTP_LENGTH0x00000221UL, CKA_OTP_TIME_INTERVAL0x00000222UL,
116 CKA_OTP_USER_FRIENDLY_MODE0x00000223UL, CKA_OTP_CHALLENGE_REQUIREMENT0x00000224UL,
117 CKA_OTP_TIME_REQUIREMENT0x00000225UL, CKA_OTP_COUNTER_REQUIREMENT0x00000226UL,
118 CKA_OTP_PIN_REQUIREMENT0x00000227UL, CKA_OTP_COUNTER0x0000022EUL, CKA_OTP_TIME0x0000022FUL,
119 CKA_OTP_USER_IDENTIFIER0x0000022AUL, CKA_OTP_SERVICE_IDENTIFIER0x0000022BUL, CKA_OTP_SERVICE_LOGO0x0000022CUL,
120 CKA_OTP_SERVICE_LOGO_TYPE0x0000022DUL, CKA_GOSTR3410_PARAMS0x00000250UL, CKA_GOSTR3411_PARAMS0x00000251UL,
121 CKA_GOST28147_PARAMS0x00000252UL, CKA_HW_FEATURE_TYPE0x00000300UL, CKA_RESET_ON_INIT0x00000301UL,
122 CKA_HAS_RESET0x00000302UL, CKA_PIXEL_X0x00000400UL, CKA_PIXEL_Y0x00000401UL, CKA_RESOLUTION0x00000402UL, CKA_CHAR_ROWS0x00000403UL,
123 CKA_CHAR_COLUMNS0x00000404UL, CKA_COLOR0x00000405UL, CKA_BITS_PER_PIXEL0x00000406UL, CKA_CHAR_SETS0x00000480UL,
124 CKA_ENCODING_METHODS0x00000481UL, CKA_MIME_TYPES0x00000482UL, CKA_MECHANISM_TYPE0x00000500UL,
125 CKA_REQUIRED_CMS_ATTRIBUTES0x00000501UL, CKA_DEFAULT_CMS_ATTRIBUTES0x00000502UL,
126 CKA_SUPPORTED_CMS_ATTRIBUTES0x00000503UL, CKA_PROFILE_ID0x00000601UL, CKA_X2RATCHET_BAG0x00000602UL,
127 CKA_X2RATCHET_BAGSIZE0x00000603UL, CKA_X2RATCHET_BOBS1STMSG0x00000604UL, CKA_X2RATCHET_CKR0x00000605UL,
128 CKA_X2RATCHET_CKS0x00000606UL, CKA_X2RATCHET_DHP0x00000607UL, CKA_X2RATCHET_DHR0x00000608UL,
129 CKA_X2RATCHET_DHS0x00000609UL, CKA_X2RATCHET_HKR0x0000060aUL, CKA_X2RATCHET_HKS0x0000060bUL,
130 CKA_X2RATCHET_ISALICE0x0000060cUL, CKA_X2RATCHET_NHKR0x0000060dUL, CKA_X2RATCHET_NHKS0x0000060eUL,
131 CKA_X2RATCHET_NR0x0000060fUL, CKA_X2RATCHET_NS0x00000610UL, CKA_X2RATCHET_PNS0x00000611UL, CKA_X2RATCHET_RK0x00000612UL,
132 CKA_HSS_LEVELS0x00000617UL, CKA_HSS_LMS_TYPE0x00000618UL, CKA_HSS_LMOTS_TYPE0x00000619UL, CKA_HSS_LMS_TYPES0x0000061aUL,
133 CKA_HSS_LMOTS_TYPES0x0000061bUL, CKA_HSS_KEYS_REMAINING0x0000061cUL, CKA_PARAMETER_SET0x0000061dUL,
134 CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL, CKA_VALIDATION_TYPE0x0000061fUL, CKA_VALIDATION_VERSION0x00000620UL,
135 CKA_VALIDATION_LEVEL0x00000621UL, CKA_VALIDATION_MODULE_ID0x00000622UL, CKA_VALIDATION_FLAG0x00000623UL,
136 CKA_VALIDATION_AUTHORITY_TYPE0x00000624UL, CKA_VALIDATION_COUNTRY0x00000625UL,
137 CKA_VALIDATION_CERTIFICATE_IDENTIFIER0x00000626UL, CKA_VALIDATION_CERTIFICATE_URI0x00000627UL,
138 CKA_VALIDATION_PROFILE0x00000629UL, CKA_VALIDATION_VENDOR_URI0x00000628UL, CKA_ENCAPSULATE_TEMPLATE0x0000062aUL,
139 CKA_DECAPSULATE_TEMPLATE0x0000062bUL, CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL,
140 CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL, CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL,
141 CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL, CKA_TRUST_IPSEC_IKE0x00000630UL,
142 CKA_PKCS_TRUST_TIME_STAMPING0x00000631UL, CKA_PKCS_TRUST_OCSP_SIGNING0x00000632UL, CKA_ENCAPSULATE0x00000633UL,
143 CKA_DECAPSULATE0x00000634UL, CKA_HASH_OF_CERTIFICATE0x00000635UL, CKA_PUBLIC_CRC64_VALUE0x00000636UL, CKA_SEED0x00000637UL,
144 CKA_NSS_TRUST0x80000001L, CKA_NSS_URL((0x80000000UL | 0x4E534350) + 1), CKA_NSS_EMAIL((0x80000000UL | 0x4E534350) + 2), CKA_NSS_SMIME_INFO((0x80000000UL | 0x4E534350) + 3),
145 CKA_NSS_SMIME_TIMESTAMP((0x80000000UL | 0x4E534350) + 4), CKA_NSS_PKCS8_SALT((0x80000000UL | 0x4E534350) + 5), CKA_NSS_PASSWORD_CHECK((0x80000000UL | 0x4E534350) + 6),
146 CKA_NSS_EXPIRES((0x80000000UL | 0x4E534350) + 7), CKA_NSS_KRL((0x80000000UL | 0x4E534350) + 8), CKA_NSS_PQG_COUNTER((0x80000000UL | 0x4E534350) + 20), CKA_NSS_PQG_SEED((0x80000000UL | 0x4E534350) + 21),
147 CKA_NSS_PQG_H((0x80000000UL | 0x4E534350) + 22), CKA_NSS_PQG_SEED_BITS((0x80000000UL | 0x4E534350) + 23), CKA_NSS_MODULE_SPEC((0x80000000UL | 0x4E534350) + 24),
148 CKA_NSS_OVERRIDE_EXTENSIONS((0x80000000UL | 0x4E534350) + 25), CKA_NSS_SERVER_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 35),
149 CKA_NSS_EMAIL_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 36), CKA_NSS_TRUST_DIGITAL_SIGNATURE(((0x80000000UL | 0x4E534350) + 0x2000) + 1),
150 CKA_NSS_TRUST_NON_REPUDIATION(((0x80000000UL | 0x4E534350) + 0x2000) + 2), CKA_NSS_TRUST_KEY_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 3),
151 CKA_NSS_TRUST_DATA_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 4), CKA_NSS_TRUST_KEY_AGREEMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 5),
152 CKA_NSS_TRUST_KEY_CERT_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 6), CKA_NSS_TRUST_CRL_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 7),
153 CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8), CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9),
154 CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10), CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11),
155 CKA_NSS_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12), CKA_NSS_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13),
156 CKA_NSS_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14), CKA_NSS_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15),
157 CKA_NSS_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16), CKA_NSS_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100),
158 CKA_NSS_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101), CKA_NSS_DB0xD5A0DB00L,
159};
160// clang-format on
161
162const size_t sftkdb_known_attributes_size = PR_ARRAY_SIZE(sftkdb_known_attributes)(sizeof(sftkdb_known_attributes) / sizeof((sftkdb_known_attributes
)[0]))
;
163
164/*
165 * Note on use of sqlReadDB: Only one thread at a time may have an actual
166 * operation going on given sqlite3 * database. An operation is defined as
167 * the time from a sqlite3_prepare() until the sqlite3_finalize().
168 * Multiple sqlite3 * databases can be open and have simultaneous operations
169 * going. We use the sqlXactDB for all write operations. This database
170 * is only opened when we first create a transaction and closed when the
171 * transaction is complete. sqlReadDB is open when we first opened the database
172 * and is used for all read operation. It's use is protected by a monitor. This
173 * is because an operation can span the use of FindObjectsInit() through the
174 * call to FindObjectsFinal(). In the intermediate time it is possible to call
175 * other operations like NSC_GetAttributeValue */
176
177struct SDBPrivateStr {
178 char *sqlDBName; /* invariant, path to this database */
179 sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
180 * by the transaction. Current transaction db*/
181 PRThread *sqlXactThread; /* protected by dbMon,
182 * current transaction thread */
183 sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
184 PRIntervalTime lastUpdateTime; /* last time the cache was updated */
185 PRIntervalTime updateInterval; /* how long the cache can go before it
186 * must be updated again */
187 sdbDataType type; /* invariant, database type */
188 char *table; /* invariant, SQL table which contains the db */
189 char *cacheTable; /* invariant, SQL table cache of db */
190 PRMonitor *dbMon; /* invariant, monitor to protect
191 * sqlXact* fields, and use of the sqlReadDB */
192 CK_ATTRIBUTE_TYPE *schemaAttrs; /* Attribute columns that exist in the table. */
193 unsigned int numSchemaAttrs;
194};
195
196typedef struct SDBPrivateStr SDBPrivate;
197
198/* Magic for an explicit NULL. NOTE: ideally this should be
199 * out of band data. Since it's not completely out of band, pick
200 * a value that has no meaning to any existing PKCS #11 attributes.
201 * This value is 1) not a valid string (imbedded '\0'). 2) not a U_LONG
202 * or a normal key (too short). 3) not a bool (too long). 4) not an RSA
203 * public exponent (too many bits).
204 */
205const unsigned char SQLITE_EXPLICIT_NULL[] = { 0xa5, 0x0, 0x5a };
206#define SQLITE_EXPLICIT_NULL_LEN3 3
207
208/*
209 * determine when we've completed our tasks
210 */
211static int
212sdb_done(int err, int *count)
213{
214 /* allow as many rows as the database wants to give */
215 if (err == SQLITE_ROW100) {
216 *count = 0;
217 return 0;
218 }
219 if (err != SQLITE_BUSY5) {
220 return 1;
221 }
222 /* err == SQLITE_BUSY, Dont' retry forever in this case */
223 if (++(*count) >= SDB_MAX_BUSY_RETRIES30) {
224 return 1;
225 }
226 return 0;
227}
228
229#if defined(_WIN32)
230/*
231 * NSPR functions and narrow CRT functions do not handle UTF-8 file paths that
232 * sqlite3 expects.
233 */
234
235static int
236sdb_chmod(const char *filename, int pmode)chmod((const char *filename), (int pmode))
237{
238 int result;
239
240 if (!filename) {
241 return -1;
242 }
243
244 wchar_t *filenameWide = _NSSUTIL_UTF8ToWide(filename);
245 if (!filenameWide) {
246 return -1;
247 }
248 result = _wchmod(filenameWide, pmode);
249 PORT_FreePORT_Free_Util(filenameWide);
250
251 return result;
252}
253#else
254#define sdb_chmod(filename, pmode)chmod((filename), (pmode)) chmod((filename), (pmode))
255#endif
256
257/*
258 * find out where sqlite stores the temp tables. We do this by replicating
259 * the logic from sqlite.
260 */
261#if defined(_WIN32)
262static char *
263sdb_getFallbackTempDir(void)
264{
265 /* sqlite uses sqlite3_temp_directory if it is not NULL. We don't have
266 * access to sqlite3_temp_directory because it is not exported from
267 * sqlite3.dll. Assume sqlite3_win32_set_directory isn't called and
268 * sqlite3_temp_directory is NULL.
269 */
270 char path[MAX_PATH];
271 DWORD rv;
272 size_t len;
273
274 rv = GetTempPathA(MAX_PATH, path);
275 if (rv > MAX_PATH || rv == 0)
276 return NULL((void*)0);
277 len = strlen(path);
278 if (len == 0)
279 return NULL((void*)0);
280 /* The returned string ends with a backslash, for example, "C:\TEMP\". */
281 if (path[len - 1] == '\\')
282 path[len - 1] = '\0';
283 return PORT_StrdupPORT_Strdup_Util(path);
284}
285#elif defined(XP_UNIX1)
286static char *
287sdb_getFallbackTempDir(void)
288{
289 const char *azDirs[] = {
290 NULL((void*)0),
291 NULL((void*)0),
292 "/var/tmp",
293 "/usr/tmp",
294 "/tmp",
295 NULL((void*)0) /* List terminator */
296 };
297 unsigned int i;
298 struct stat buf;
299 const char *zDir = NULL((void*)0);
300
301 azDirs[0] = sqlite3_temp_directory;
302 azDirs[1] = PR_GetEnvSecure("TMPDIR");
303
304 for (i = 0; i < PR_ARRAY_SIZE(azDirs)(sizeof(azDirs) / sizeof((azDirs)[0])); i++) {
305 zDir = azDirs[i];
306 if (zDir == NULL((void*)0))
307 continue;
308 if (stat(zDir, &buf))
309 continue;
310 if (!S_ISDIR(buf.st_mode)((((buf.st_mode)) & 0170000) == (0040000)))
311 continue;
312 if (access(zDir, 07))
313 continue;
314 break;
315 }
316
317 if (zDir == NULL((void*)0))
318 return NULL((void*)0);
319 return PORT_StrdupPORT_Strdup_Util(zDir);
320}
321#else
322#error "sdb_getFallbackTempDir not implemented"
323#endif
324
325#ifndef SQLITE_FCNTL_TEMPFILENAME16
326/* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */
327#define SQLITE_FCNTL_TEMPFILENAME16 16
328#endif
329
330static char *
331sdb_getTempDir(sqlite3 *sqlDB)
332{
333 int sqlrv;
334 char *result = NULL((void*)0);
335 char *tempName = NULL((void*)0);
336 char *foundSeparator = NULL((void*)0);
337
338 /* Obtain temporary filename in sqlite's directory for temporary tables */
339 sqlrv = sqlite3_file_control(sqlDB, 0, SQLITE_FCNTL_TEMPFILENAME16,
340 (void *)&tempName);
341 if (sqlrv == SQLITE_NOTFOUND12) {
342 /* SQLITE_FCNTL_TEMPFILENAME not implemented because we are using
343 * an older SQLite. */
344 return sdb_getFallbackTempDir();
345 }
346 if (sqlrv != SQLITE_OK0) {
347 return NULL((void*)0);
348 }
349
350 /* We'll extract the temporary directory from tempName */
351 foundSeparator = PORT_Strrchrstrrchr(tempName, PR_GetDirectorySeparator());
352 if (foundSeparator) {
353 /* We shorten the temp filename string to contain only
354 * the directory name (including the trailing separator).
355 * We know the byte after the foundSeparator position is
356 * safe to use, in the shortest scenario it contains the
357 * end-of-string byte.
358 * By keeping the separator at the found position, it will
359 * even work if tempDir consists of the separator, only.
360 * (In this case the toplevel directory will be used for
361 * access speed testing). */
362 ++foundSeparator;
363 *foundSeparator = 0;
364
365 /* Now we copy the directory name for our caller */
366 result = PORT_StrdupPORT_Strdup_Util(tempName);
367 }
368
369 sqlite3_free(tempName);
370 return result;
371}
372
373/*
374 * Map SQL_LITE errors to PKCS #11 errors as best we can.
375 */
376static CK_RV
377sdb_mapSQLError(sdbDataType type, int sqlerr)
378{
379 switch (sqlerr) {
380 /* good matches */
381 case SQLITE_OK0:
382 case SQLITE_DONE101:
383 return CKR_OK0x00000000UL;
384 case SQLITE_NOMEM7:
385 return CKR_HOST_MEMORY0x00000002UL;
386 case SQLITE_READONLY8:
387 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
388 /* close matches */
389 case SQLITE_AUTH23:
390 case SQLITE_PERM3:
391 /*return CKR_USER_NOT_LOGGED_IN; */
392 case SQLITE_CANTOPEN14:
393 case SQLITE_NOTFOUND12:
394 /* NSS distiguishes between failure to open the cert and the key db */
395 return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED((0x80000000UL | 0x4E534350) + 1) : CKR_NSS_KEYDB_FAILED((0x80000000UL | 0x4E534350) + 2);
396 case SQLITE_IOERR10:
397 return CKR_DEVICE_ERROR0x00000030UL;
398 default:
399 break;
400 }
401 return CKR_GENERAL_ERROR0x00000005UL;
402}
403
404/*
405 * build up database name from a directory, prefix, name, version and flags.
406 */
407static char *
408sdb_BuildFileName(const char *directory,
409 const char *prefix, const char *type,
410 int version)
411{
412 char *dbname = NULL((void*)0);
413 /* build the full dbname */
414 dbname = sqlite3_mprintf("%s%c%s%s%d.db", directory,
415 (int)(unsigned char)PR_GetDirectorySeparator(),
416 prefix, type, version);
417 return dbname;
418}
419
420/*
421 * find out how expensive the access system call is for non-existant files
422 * in the given directory. Return the number of operations done in 33 ms.
423 */
424static PRUint32
425sdb_measureAccess(const char *directory)
426{
427 PRUint32 i;
428 PRIntervalTime time;
429 PRIntervalTime delta;
430 PRIntervalTime duration = PR_MillisecondsToInterval(33);
431 const char *doesntExistName = "_dOeSnotExist_.db";
432 char *temp, *tempStartOfFilename;
433 size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
434#ifdef SDB_MEASURE_USE_TEMP_DIR1
435 /*
436 * on some OS's and Filesystems, creating a bunch of files and deleting
437 * them messes up the systems's caching, but if we create the files in
438 * a temp directory which we later delete, then the cache gets cleared
439 * up. This code uses several OS dependent calls, and it's not clear
440 * that temp directory use won't mess up other filesystems and OS caching,
441 * so if you need this for your OS, you can turn on the
442 * 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf
443 */
444 const char template[] = "dbTemp.XXXXXX";
445 tmpdirLength = sizeof(template);
446#endif
447 /* no directory, just return one */
448 if (directory == NULL((void*)0)) {
449 return 1;
450 }
451
452 /* our calculation assumes time is a 4 bytes == 32 bit integer */
453 PORT_Assert(sizeof(time) == 4)((sizeof(time) == 4) ? ((void)0) : PR_Assert("sizeof(time) == 4"
, "/root/firefox-clang/security/nss/lib/softoken/sdb.c", 453)
)
;
454
455 directoryLength = strlen(directory);
456
457 maxTempLen = directoryLength + 1 /* dirname + / */
458 + tmpdirLength /* tmpdirname includes / */
459 + strlen(doesntExistName) /* filename base */
460 + 11 /* max chars for 32 bit int plus potential sign */
461 + 1; /* zero terminator */
462
463 temp = PORT_ZAllocPORT_ZAlloc_Util(maxTempLen);
464 if (!temp) {
465 return 1;
466 }
467
468 /* We'll copy directory into temp just once, then ensure it ends
469 * with the directory separator. */
470
471 strcpy(temp, directory);
472 if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
473 temp[directoryLength++] = PR_GetDirectorySeparator();
474 }
475
476#ifdef SDB_MEASURE_USE_TEMP_DIR1
477 /* add the template for a temporary subdir, and create it */
478 strcat(temp, template);
479 if (!mkdtemp(temp)) {
480 PORT_FreePORT_Free_Util(temp);
481 return 1;
482 }
483 /* and terminate that tmp subdir with a / */
484 strcat(temp, "/");
485#endif
486
487 /* Remember the position after the last separator, and calculate the
488 * number of remaining bytes. */
489 tempStartOfFilename = temp + directoryLength + tmpdirLength;
490 maxFileNameLen = maxTempLen - directoryLength;
491
492 /* measure number of Access operations that can be done in 33 milliseconds
493 * (1/30'th of a second), or 10000 operations, which ever comes first.
494 */
495 time = PR_IntervalNow();
496 for (i = 0; i < 10000u; i++) {
497 PRIntervalTime next;
498
499 /* We'll use the variable part first in the filename string, just in
500 * case it's longer than assumed, so if anything gets cut off, it
501 * will be cut off from the constant part.
502 * This code assumes the directory name at the beginning of
503 * temp remains unchanged during our loop. */
504 PR_snprintf(tempStartOfFilename, maxFileNameLen,
505 ".%lu%s", (PRUint32)(time + i), doesntExistName);
506 PR_Access(temp, PR_ACCESS_EXISTS);
507 next = PR_IntervalNow();
508 delta = next - time;
509 if (delta >= duration)
510 break;
511 }
512
513#ifdef SDB_MEASURE_USE_TEMP_DIR1
514 /* turn temp back into our tmpdir path by removing doesntExistName, and
515 * remove the tmp dir */
516 *tempStartOfFilename = '\0';
517 (void)rmdir(temp);
518#endif
519 PORT_FreePORT_Free_Util(temp);
520
521 /* always return 1 or greater */
522 return i ? i : 1u;
523}
524
525/*
526 * some file sytems are very slow to run sqlite3 on, particularly if the
527 * access count is pretty high. On these filesystems is faster to create
528 * a temporary database on the local filesystem and access that. This
529 * code uses a temporary table to create that cache. Temp tables are
530 * automatically cleared when the database handle it was created on
531 * Is freed.
532 */
533static const char DROP_CACHE_CMD[] = "DROP TABLE %s";
534static const char CREATE_CACHE_CMD[] =
535 "CREATE TEMPORARY TABLE %s AS SELECT * FROM %s";
536static const char CREATE_ISSUER_INDEX_CMD[] =
537 "CREATE INDEX issuer ON %s (a81)";
538static const char CREATE_SUBJECT_INDEX_CMD[] =
539 "CREATE INDEX subject ON %s (a101)";
540static const char CREATE_LABEL_INDEX_CMD[] = "CREATE INDEX label ON %s (a3)";
541static const char CREATE_ID_INDEX_CMD[] = "CREATE INDEX ckaid ON %s (a102)";
542
543static CK_RV
544sdb_buildCache(sqlite3 *sqlDB, sdbDataType type,
545 const char *cacheTable, const char *table)
546{
547 char *newStr;
548 int sqlerr = SQLITE_OK0;
549
550 newStr = sqlite3_mprintf(CREATE_CACHE_CMD, cacheTable, table);
551 if (newStr == NULL((void*)0)) {
552 return CKR_HOST_MEMORY0x00000002UL;
553 }
554 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
555 sqlite3_free(newStr);
556 if (sqlerr != SQLITE_OK0) {
557 return sdb_mapSQLError(type, sqlerr);
558 }
559 /* failure to create the indexes is not an issue */
560 newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, cacheTable);
561 if (newStr == NULL((void*)0)) {
562 return CKR_OK0x00000000UL;
563 }
564 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
565 sqlite3_free(newStr);
566 newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, cacheTable);
567 if (newStr == NULL((void*)0)) {
568 return CKR_OK0x00000000UL;
569 }
570 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
571 sqlite3_free(newStr);
572 newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, cacheTable);
573 if (newStr == NULL((void*)0)) {
574 return CKR_OK0x00000000UL;
575 }
576 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
577 sqlite3_free(newStr);
578 newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, cacheTable);
579 if (newStr == NULL((void*)0)) {
580 return CKR_OK0x00000000UL;
581 }
582 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
583 sqlite3_free(newStr);
584 return CKR_OK0x00000000UL;
585}
586
587/*
588 * update the cache and the data records describing it.
589 * The cache is updated by dropping the temp database and recreating it.
590 */
591static CK_RV
592sdb_updateCache(SDBPrivate *sdb_p)
593{
594 int sqlerr = SQLITE_OK0;
595 CK_RV error = CKR_OK0x00000000UL;
596 char *newStr;
597
598 /* drop the old table */
599 newStr = sqlite3_mprintf(DROP_CACHE_CMD, sdb_p->cacheTable);
600 if (newStr == NULL((void*)0)) {
601 return CKR_HOST_MEMORY0x00000002UL;
602 }
603 sqlerr = sqlite3_exec(sdb_p->sqlReadDB, newStr, NULL((void*)0), 0, NULL((void*)0));
604 sqlite3_free(newStr);
605 if ((sqlerr != SQLITE_OK0) && (sqlerr != SQLITE_ERROR1)) {
606 /* something went wrong with the drop, don't try to refresh...
607 * NOTE: SQLITE_ERROR is returned if the table doesn't exist. In
608 * that case, we just continue on and try to reload it */
609 return sdb_mapSQLError(sdb_p->type, sqlerr);
610 }
611
612 /* set up the new table */
613 error = sdb_buildCache(sdb_p->sqlReadDB, sdb_p->type,
614 sdb_p->cacheTable, sdb_p->table);
615 if (error == CKR_OK0x00000000UL) {
616 /* we have a new cache! */
617 sdb_p->lastUpdateTime = PR_IntervalNow();
618 }
619 return error;
620}
621
622/*
623 * The sharing of sqlite3 handles across threads is tricky. Older versions
624 * couldn't at all, but newer ones can under strict conditions. Basically
625 * no 2 threads can use the same handle while another thread has an open
626 * stmt running. Once the sqlite3_stmt is finalized, another thread can then
627 * use the database handle.
628 *
629 * We use monitors to protect against trying to use a database before
630 * it's sqlite3_stmt is finalized. This is preferable to the opening and
631 * closing the database each operation because there is significant overhead
632 * in the open and close. Also continually opening and closing the database
633 * defeats the cache code as the cache table is lost on close (thus
634 * requiring us to have to reinitialize the cache every operation).
635 *
636 * An execption to the shared handle is transations. All writes happen
637 * through a transaction. When we are in a transaction, we must use the
638 * same database pointer for that entire transation. In this case we save
639 * the transaction database and use it for all accesses on the transaction
640 * thread. Other threads use the common database.
641 *
642 * There can only be once active transaction on the database at a time.
643 *
644 * sdb_openDBLocal() provides us with a valid database handle for whatever
645 * state we are in (reading or in a transaction), and acquires any locks
646 * appropriate to that state. It also decides when it's time to refresh
647 * the cache before we start an operation. Any database handle returned
648 * just eventually be closed with sdb_closeDBLocal().
649 *
650 * The table returned either points to the database's physical table, or
651 * to the cached shadow. Tranactions always return the physical table
652 * and read operations return either the physical table or the cache
653 * depending on whether or not the cache exists.
654 */
655static CK_RV
656sdb_openDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB, const char **table)
657{
658 *sqlDB = NULL((void*)0);
659
660 PR_EnterMonitor(sdb_p->dbMon);
661
662 if (table) {
663 *table = sdb_p->table;
664 }
665
666 /* We're in a transaction, use the transaction DB */
667 if ((sdb_p->sqlXactDB) && (sdb_p->sqlXactThread == PR_GetCurrentThread())) {
668 *sqlDB = sdb_p->sqlXactDB;
669 /* only one thread can get here, safe to unlock */
670 PR_ExitMonitor(sdb_p->dbMon);
671 return CKR_OK0x00000000UL;
672 }
673
674 /*
675 * if we are just reading from the table, we may have the table
676 * cached in a temporary table (especially if it's on a shared FS).
677 * In that case we want to see updates to the table, the the granularity
678 * is on order of human scale, not computer scale.
679 */
680 if (table && sdb_p->cacheTable) {
681 PRIntervalTime now = PR_IntervalNow();
682 if ((now - sdb_p->lastUpdateTime) > sdb_p->updateInterval) {
683 sdb_updateCache(sdb_p);
684 }
685 *table = sdb_p->cacheTable;
686 }
687
688 *sqlDB = sdb_p->sqlReadDB;
689
690 /* leave holding the lock. only one thread can actually use a given
691 * database connection at once */
692
693 return CKR_OK0x00000000UL;
694}
695
696/* closing the local database currenly means unlocking the monitor */
697static CK_RV
698sdb_closeDBLocal(SDBPrivate *sdb_p, sqlite3 *sqlDB)
699{
700 if (sdb_p->sqlXactDB != sqlDB) {
701 /* if we weren't in a transaction, we got a lock */
702 PR_ExitMonitor(sdb_p->dbMon);
703 }
704 return CKR_OK0x00000000UL;
705}
706
707/*
708 * wrapper to sqlite3_open which also sets the busy_timeout
709 */
710static int
711sdb_openDB(const char *name, sqlite3 **sqlDB, int flags)
712{
713 int sqlerr;
714 int openFlags;
715
716 *sqlDB = NULL((void*)0);
717
718 if (flags & SDB_RDONLY1) {
719 openFlags = SQLITE_OPEN_READONLY0x00000001;
720 } else {
721 openFlags = SQLITE_OPEN_READWRITE0x00000002 | SQLITE_OPEN_CREATE0x00000004;
722 /* sqlite 3.34 seem to incorrectly open readwrite.
723 * when the file is readonly. Explicitly reject that issue here */
724 if ((_NSSUTIL_Access(name, PR_ACCESS_EXISTS)PR_Access((name), (PR_ACCESS_EXISTS)) == PR_SUCCESS) && (_NSSUTIL_Access(name, PR_ACCESS_WRITE_OK)PR_Access((name), (PR_ACCESS_WRITE_OK)) != PR_SUCCESS)) {
725 return SQLITE_READONLY8;
726 }
727 }
728
729 /* Requires SQLite 3.5.0 or newer. */
730 sqlerr = sqlite3_open_v2(name, sqlDB, openFlags, NULL((void*)0));
731 if (sqlerr != SQLITE_OK0) {
732 return sqlerr;
733 }
734
735 sqlerr = sqlite3_busy_timeout(*sqlDB, SDB_SQLITE_BUSY_TIMEOUT1000);
736 if (sqlerr != SQLITE_OK0) {
737 sqlite3_close(*sqlDB);
738 *sqlDB = NULL((void*)0);
739 return sqlerr;
740 }
741 return SQLITE_OK0;
742}
743
744/* Sigh, if we created a new table since we opened the database,
745 * the database handle will not see the new table, we need to close this
746 * database and reopen it. Caller must be in a transaction or holding
747 * the dbMon. sqlDB is changed on success. */
748static int
749sdb_reopenDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB)
750{
751 sqlite3 *newDB;
752 int sqlerr;
753
754 /* open a new database */
755 sqlerr = sdb_openDB(sdb_p->sqlDBName, &newDB, SDB_RDONLY1);
756 if (sqlerr != SQLITE_OK0) {
757 return sqlerr;
758 }
759
760 /* if we are in a transaction, we may not be holding the monitor.
761 * grab it before we update the transaction database. This is
762 * safe since are using monitors. */
763 PR_EnterMonitor(sdb_p->dbMon);
764 /* update our view of the database */
765 if (sdb_p->sqlReadDB == *sqlDB) {
766 sdb_p->sqlReadDB = newDB;
767 } else if (sdb_p->sqlXactDB == *sqlDB) {
768 sdb_p->sqlXactDB = newDB;
769 }
770 PR_ExitMonitor(sdb_p->dbMon);
771
772 /* close the old one */
773 sqlite3_close(*sqlDB);
774
775 *sqlDB = newDB;
776 return SQLITE_OK0;
777}
778
779struct SDBFindStr {
780 sqlite3 *sqlDB;
781 sqlite3_stmt *findstmt;
782};
783
784static const char FIND_OBJECTS_CMD[] = "SELECT ALL id FROM %s WHERE %s;";
785static const char FIND_OBJECTS_ALL_CMD[] = "SELECT ALL id FROM %s;";
786CK_RV
787sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count,
788 SDBFind **find)
789{
790 SDBPrivate *sdb_p = sdb->private;
791 sqlite3 *sqlDB = NULL((void*)0);
792 const char *table;
793 char *newStr, *findStr = NULL((void*)0);
794 sqlite3_stmt *findstmt = NULL((void*)0);
795 char *join = "";
796 int sqlerr = SQLITE_OK0;
797 CK_RV error = CKR_OK0x00000000UL;
798 unsigned int i;
799
800 LOCK_SQLITE()
801 *find = NULL((void*)0);
802 error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
803 if (error != CKR_OK0x00000000UL) {
804 goto loser;
805 }
806
807 findStr = sqlite3_mprintf("");
808 for (i = 0; findStr && i < count; i++) {
809 newStr = sqlite3_mprintf("%s%sa%x=$DATA%d", findStr, join,
810 template[i].type, i);
811 join = " AND ";
812 sqlite3_free(findStr);
813 findStr = newStr;
814 }
815
816 if (findStr == NULL((void*)0)) {
817 error = CKR_HOST_MEMORY0x00000002UL;
818 goto loser;
819 }
820
821 if (count == 0) {
822 newStr = sqlite3_mprintf(FIND_OBJECTS_ALL_CMD, table);
823 } else {
824 newStr = sqlite3_mprintf(FIND_OBJECTS_CMD, table, findStr);
825 }
826 sqlite3_free(findStr);
827 if (newStr == NULL((void*)0)) {
828 error = CKR_HOST_MEMORY0x00000002UL;
829 goto loser;
830 }
831 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &findstmt, NULL((void*)0));
832 sqlite3_free(newStr);
833 for (i = 0; sqlerr == SQLITE_OK0 && i < count; i++) {
834 const void *blobData = template[i].pValue;
835 CK_ULONG blobSize = template[i].ulValueLen;
836 if (blobSize == 0) {
837 blobData = SQLITE_EXPLICIT_NULL;
838 blobSize = SQLITE_EXPLICIT_NULL_LEN3;
839 } else if (blobSize > INT_MAX2147483647) {
840 error = CKR_ARGUMENTS_BAD0x00000007UL;
841 goto loser;
842 }
843 sqlerr = sqlite3_bind_blob(findstmt, i + 1, blobData, (int)blobSize,
844 SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
845 }
846 if (sqlerr == SQLITE_OK0) {
847 *find = PORT_New(SDBFind)(SDBFind *)PORT_Alloc_Util(sizeof(SDBFind));
848 if (*find == NULL((void*)0)) {
849 error = CKR_HOST_MEMORY0x00000002UL;
850 goto loser;
851 }
852 (*find)->findstmt = findstmt;
853 (*find)->sqlDB = sqlDB;
854 UNLOCK_SQLITE()
855 return CKR_OK0x00000000UL;
856 }
857 error = sdb_mapSQLError(sdb_p->type, sqlerr);
858
859loser:
860 if (findstmt) {
861 sqlite3_reset(findstmt);
862 sqlite3_finalize(findstmt);
863 }
864 if (sqlDB) {
865 sdb_closeDBLocal(sdb_p, sqlDB);
866 }
867 UNLOCK_SQLITE()
868 return error;
869}
870
871CK_RV
872sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object,
873 CK_ULONG arraySize, CK_ULONG *count)
874{
875 SDBPrivate *sdb_p = sdb->private;
876 sqlite3_stmt *stmt = sdbFind->findstmt;
877 int sqlerr = SQLITE_OK0;
878 int retry = 0;
879
880 *count = 0;
881
882 if (arraySize == 0) {
883 return CKR_OK0x00000000UL;
884 }
885 LOCK_SQLITE()
886
887 do {
888 sqlerr = sqlite3_step(stmt);
889 if (sqlerr == SQLITE_BUSY5) {
890 PR_Sleep(SDB_BUSY_RETRY_TIME5);
891 }
892 if (sqlerr == SQLITE_ROW100) {
893 /* only care about the id */
894 *object++ = sqlite3_column_int(stmt, 0);
895 arraySize--;
896 (*count)++;
897 }
898 } while (!sdb_done(sqlerr, &retry) && (arraySize > 0));
899
900 /* we only have some of the objects, there is probably more,
901 * set the sqlerr to an OK value so we return CKR_OK */
902 if (sqlerr == SQLITE_ROW100 && arraySize == 0) {
903 sqlerr = SQLITE_DONE101;
904 }
905 UNLOCK_SQLITE()
906
907 return sdb_mapSQLError(sdb_p->type, sqlerr);
908}
909
910CK_RV
911sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
912{
913 SDBPrivate *sdb_p = sdb->private;
914 sqlite3_stmt *stmt = sdbFind->findstmt;
915 sqlite3 *sqlDB = sdbFind->sqlDB;
916 int sqlerr = SQLITE_OK0;
917
918 LOCK_SQLITE()
919 if (stmt) {
920 sqlite3_reset(stmt);
921 sqlerr = sqlite3_finalize(stmt);
922 }
923 if (sqlDB) {
924 sdb_closeDBLocal(sdb_p, sqlDB);
925 }
926 PORT_FreePORT_Free_Util(sdbFind);
927
928 UNLOCK_SQLITE()
929 return sdb_mapSQLError(sdb_p->type, sqlerr);
930}
931
932static CK_RV
933sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
934 CK_ATTRIBUTE *template, CK_ULONG count)
935{
936 SDBPrivate *sdb_p = sdb->private;
937 sqlite3 *sqlDB = NULL((void*)0);
938 sqlite3_stmt *stmt = NULL((void*)0);
939 const char *table = NULL((void*)0);
940 int sqlerr = SQLITE_OK0;
941 CK_RV error = CKR_OK0x00000000UL;
942 int found = 0;
943 int retry = 0;
944 unsigned int i;
945
946 if (count == 0) {
947 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
948 goto loser;
949 }
950
951 /* open a new db if necessary */
952 error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
953 if (error != CKR_OK0x00000000UL) {
954 goto loser;
955 }
956
957 char *columns = NULL((void*)0);
958 for (i = 0; i < count; i++) {
959 char *newColumns;
960 if (columns) {
961 newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
962 sqlite3_free(columns);
963 columns = NULL((void*)0);
964 } else {
965 newColumns = sqlite3_mprintf("a%x", template[i].type);
966 }
967 if (!newColumns) {
968 error = CKR_HOST_MEMORY0x00000002UL;
969 goto loser;
970 }
971 columns = newColumns;
972 }
973
974 PORT_Assert(columns)((columns) ? ((void)0) : PR_Assert("columns", "/root/firefox-clang/security/nss/lib/softoken/sdb.c"
, 974))
;
975
976 char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
977 columns, table);
978 sqlite3_free(columns);
979 columns = NULL((void*)0);
980 if (!statement) {
981 error = CKR_HOST_MEMORY0x00000002UL;
982 goto loser;
983 }
984
985 sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL((void*)0));
986 sqlite3_free(statement);
987 statement = NULL((void*)0);
988 if (sqlerr != SQLITE_OK0) {
989 goto loser;
990 }
991
992 // NB: indices in sqlite3_bind_int are 1-indexed
993 sqlerr = sqlite3_bind_int(stmt, 1, object_id);
994 if (sqlerr != SQLITE_OK0) {
995 goto loser;
996 }
997
998 do {
999 sqlerr = sqlite3_step(stmt);
1000 if (sqlerr == SQLITE_BUSY5) {
1001 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1002 }
1003 if (sqlerr == SQLITE_ROW100) {
1004 PORT_Assert(!found)((!found) ? ((void)0) : PR_Assert("!found", "/root/firefox-clang/security/nss/lib/softoken/sdb.c"
, 1004))
;
1005 for (i = 0; i < count; i++) {
1006 unsigned int blobSize;
1007 const char *blobData;
1008
1009 // NB: indices in sqlite_column_{bytes,blob} are 0-indexed
1010 blobSize = sqlite3_column_bytes(stmt, i);
1011 blobData = sqlite3_column_blob(stmt, i);
1012 if (blobData == NULL((void*)0)) {
1013 /* PKCS 11 requires that get attributes process all the
1014 * attributes in the template, marking the attributes with
1015 * issues with -1. Mark the error but continue */
1016 template[i].ulValueLen = -1;
1017 error = CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL;
1018 continue;
1019 }
1020 /* If the blob equals our explicit NULL value, then the
1021 * attribute is a NULL. */
1022 if ((blobSize == SQLITE_EXPLICIT_NULL_LEN3) &&
1023 (PORT_Memcmpmemcmp(blobData, SQLITE_EXPLICIT_NULL,
1024 SQLITE_EXPLICIT_NULL_LEN3) == 0)) {
1025 blobSize = 0;
1026 }
1027 if (template[i].pValue) {
1028 if (template[i].ulValueLen < blobSize) {
1029 /* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
1030 template[i].ulValueLen = -1;
1031 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1032 continue;
1033 }
1034 PORT_Memcpymemcpy(template[i].pValue, blobData, blobSize);
1035 }
1036 template[i].ulValueLen = blobSize;
1037 }
1038 found = 1;
1039 }
1040 } while (!sdb_done(sqlerr, &retry));
1041
1042 sqlite3_reset(stmt);
1043 sqlite3_finalize(stmt);
1044 stmt = NULL((void*)0);
1045
1046loser:
1047 /* fix up the error if necessary */
1048 if (error == CKR_OK0x00000000UL) {
1049 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1050 if (!found && error == CKR_OK0x00000000UL) {
1051 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1052 }
1053 }
1054
1055 if (stmt) {
1056 sqlite3_reset(stmt);
1057 sqlite3_finalize(stmt);
1058 }
1059
1060 /* if we had to open a new database, free it now */
1061 if (sqlDB) {
1062 sdb_closeDBLocal(sdb_p, sqlDB);
1063 }
1064 return error;
1065}
1066
1067/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */
1068inline static PRBool
1069sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr)
1070{
1071 SDBPrivate *sdb_p = sdb->private;
1072 int first = 0;
1073 int last = (int)sdb_p->numSchemaAttrs - 1;
1074 while (last >= first) {
1075 int mid = first + (last - first) / 2;
1076 if (sdb_p->schemaAttrs[mid] == attr) {
1077 return PR_TRUE1;
1078 }
1079 if (attr > sdb_p->schemaAttrs[mid]) {
1080 first = mid + 1;
1081 } else {
1082 last = mid - 1;
1083 }
1084 }
1085
1086 return PR_FALSE0;
1087}
1088
1089CK_RV
1090sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1091 CK_ATTRIBUTE *template, CK_ULONG count)
1092{
1093 CK_RV crv = CKR_OK0x00000000UL;
1094 unsigned int tmplIdx;
1095 unsigned int resIdx = 0;
1096 unsigned int validCount = 0;
1097 unsigned int i;
1098
1099 if (count == 0) {
1100 return crv;
1101 }
1102
1103 CK_ATTRIBUTE *validTemplate;
1104 PRBool invalidExists = PR_FALSE0;
1105 for (tmplIdx = 0; tmplIdx < count; tmplIdx++) {
1106 if (!sdb_attributeExists(sdb, template[tmplIdx].type)) {
1107 template[tmplIdx].ulValueLen = -1;
1108 crv = CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL;
1109 invalidExists = PR_TRUE1;
1110 break;
1111 }
1112 }
1113
1114 if (!invalidExists) {
1115 validTemplate = template;
1116 validCount = count;
1117 } else {
1118 /* Create a new template containing only the valid subset of
1119 * input |template|, and query with that. */
1120 validCount = tmplIdx;
1121 validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count);
1122 if (!validTemplate) {
1123 return CKR_HOST_MEMORY0x00000002UL;
1124 }
1125 /* Copy in what we already know is valid. */
1126 for (i = 0; i < validCount; i++) {
1127 validTemplate[i] = template[i];
1128 }
1129
1130 /* tmplIdx was left at the index of the first invalid
1131 * attribute, which has been handled. We only need to
1132 * deal with the remainder. */
1133 tmplIdx++;
1134 for (; tmplIdx < count; tmplIdx++) {
1135 if (sdb_attributeExists(sdb, template[tmplIdx].type)) {
1136 validTemplate[validCount++] = template[tmplIdx];
1137 } else {
1138 template[tmplIdx].ulValueLen = -1;
1139 }
1140 }
1141 }
1142
1143 if (validCount) {
1144 LOCK_SQLITE()
1145 CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount);
1146 UNLOCK_SQLITE()
1147
1148 /* If an invalid attribute was removed above, let
1149 * the caller know. Any other error from the actual
1150 * query should propogate. */
1151 crv = (crv2 == CKR_OK0x00000000UL) ? crv : crv2;
1152 }
1153
1154 if (invalidExists) {
1155 /* Copy out valid lengths. */
1156 tmplIdx = 0;
1157 for (resIdx = 0; resIdx < validCount; resIdx++) {
1158 for (; tmplIdx < count; tmplIdx++) {
1159 if (template[tmplIdx].type != validTemplate[resIdx].type) {
1160 continue;
1161 }
1162 template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen;
1163 tmplIdx++;
1164 break;
1165 }
1166 }
1167 free(validTemplate);
1168 }
1169
1170 return crv;
1171}
1172
1173static const char SET_ATTRIBUTE_CMD[] = "UPDATE %s SET %s WHERE id=$ID;";
1174CK_RV
1175sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
1176 const CK_ATTRIBUTE *template, CK_ULONG count)
1177{
1178 SDBPrivate *sdb_p = sdb->private;
1179 sqlite3 *sqlDB = NULL((void*)0);
1180 sqlite3_stmt *stmt = NULL((void*)0);
1181 char *setStr = NULL((void*)0);
1182 char *newStr = NULL((void*)0);
1183 int sqlerr = SQLITE_OK0;
1184 int retry = 0;
1185 CK_RV error = CKR_OK0x00000000UL;
1186 unsigned int i;
1187
1188 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1189 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1190 }
1191
1192 if (count == 0) {
1193 return CKR_OK0x00000000UL;
1194 }
1195
1196 LOCK_SQLITE()
1197 setStr = sqlite3_mprintf("");
1198 for (i = 0; setStr && i < count; i++) {
1199 if (i == 0) {
1200 sqlite3_free(setStr);
1201 setStr = sqlite3_mprintf("a%x=$VALUE%d",
1202 template[i].type, i);
1203 continue;
1204 }
1205 newStr = sqlite3_mprintf("%s,a%x=$VALUE%d", setStr,
1206 template[i].type, i);
1207 sqlite3_free(setStr);
1208 setStr = newStr;
1209 }
1210 newStr = NULL((void*)0);
1211
1212 if (setStr == NULL((void*)0)) {
1213 return CKR_HOST_MEMORY0x00000002UL;
1214 }
1215 newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr);
1216 sqlite3_free(setStr);
1217 if (newStr == NULL((void*)0)) {
1218 UNLOCK_SQLITE()
1219 return CKR_HOST_MEMORY0x00000002UL;
1220 }
1221 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1222 if (error != CKR_OK0x00000000UL) {
1223 goto loser;
1224 }
1225 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1226 if (sqlerr != SQLITE_OK0)
1227 goto loser;
1228 for (i = 0; i < count; i++) {
1229 if (template[i].ulValueLen != 0) {
1230 sqlerr = sqlite3_bind_blob(stmt, i + 1, template[i].pValue,
1231 template[i].ulValueLen, SQLITE_STATIC((sqlite3_destructor_type)0));
1232 } else {
1233 sqlerr = sqlite3_bind_blob(stmt, i + 1, SQLITE_EXPLICIT_NULL,
1234 SQLITE_EXPLICIT_NULL_LEN3, SQLITE_STATIC((sqlite3_destructor_type)0));
1235 }
1236 if (sqlerr != SQLITE_OK0)
1237 goto loser;
1238 }
1239 sqlerr = sqlite3_bind_int(stmt, i + 1, object_id);
1240 if (sqlerr != SQLITE_OK0)
1241 goto loser;
1242
1243 do {
1244 sqlerr = sqlite3_step(stmt);
1245 if (sqlerr == SQLITE_BUSY5) {
1246 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1247 }
1248 } while (!sdb_done(sqlerr, &retry));
1249
1250loser:
1251 if (newStr) {
1252 sqlite3_free(newStr);
1253 }
1254 if (error == CKR_OK0x00000000UL) {
1255 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1256 }
1257
1258 if (stmt) {
1259 sqlite3_reset(stmt);
1260 sqlite3_finalize(stmt);
1261 }
1262
1263 if (sqlDB) {
1264 sdb_closeDBLocal(sdb_p, sqlDB);
1265 }
1266
1267 UNLOCK_SQLITE()
1268 return error;
1269}
1270
1271/*
1272 * check to see if a candidate object handle already exists.
1273 */
1274static PRBool
1275sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
1276{
1277 CK_RV crv;
1278 CK_ATTRIBUTE template = { CKA_LABEL0x00000003UL, NULL((void*)0), 0 };
1279
1280 crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1);
1281 if (crv == CKR_OBJECT_HANDLE_INVALID0x00000082UL) {
1282 return PR_FALSE0;
1283 }
1284 return PR_TRUE1;
1285}
1286
1287/*
1288 * if we're here, we are in a transaction, so it's safe
1289 * to examine the current state of the database
1290 */
1291static CK_OBJECT_HANDLE
1292sdb_getObjectId(SDB *sdb)
1293{
1294 CK_OBJECT_HANDLE candidate;
1295 static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE0;
1296 int count;
1297 /*
1298 * get an initial object handle to use
1299 */
1300 if (next_obj == CK_INVALID_HANDLE0) {
1301 PRTime time;
1302 time = PR_Now();
1303
1304 next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL);
1305 }
1306 candidate = next_obj++;
1307 /* detect that we've looped through all the handles... */
1308 for (count = 0; count < 0x40000000; count++, candidate = next_obj++) {
1309 /* mask off excess bits */
1310 candidate &= 0x3fffffff;
1311 /* if we hit zero, go to the next entry */
1312 if (candidate == CK_INVALID_HANDLE0) {
1313 continue;
1314 }
1315 /* make sure we aren't already using */
1316 if (!sdb_objectExists(sdb, candidate)) {
1317 /* this one is free */
1318 return candidate;
1319 }
1320 }
1321
1322 /* no handle is free, fail */
1323 return CK_INVALID_HANDLE0;
1324}
1325
1326CK_RV
1327sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object)
1328{
1329 CK_OBJECT_HANDLE id;
1330
1331 id = sdb_getObjectId(sdb);
1332 if (id == CK_INVALID_HANDLE0) {
1333 return CKR_DEVICE_MEMORY0x00000031UL; /* basically we ran out of resources */
1334 }
1335 *object = id;
1336 return CKR_OK0x00000000UL;
1337}
1338
1339static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);";
1340CK_RV
1341sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
1342 const CK_ATTRIBUTE *template, CK_ULONG count)
1343{
1344 SDBPrivate *sdb_p = sdb->private;
1345 sqlite3 *sqlDB = NULL((void*)0);
1346 sqlite3_stmt *stmt = NULL((void*)0);
1347 char *columnStr = NULL((void*)0);
1348 char *valueStr = NULL((void*)0);
1349 char *newStr = NULL((void*)0);
1350 int sqlerr = SQLITE_OK0;
1351 CK_RV error = CKR_OK0x00000000UL;
1352 CK_OBJECT_HANDLE this_object = CK_INVALID_HANDLE0;
1353 int retry = 0;
1354 unsigned int i;
1355
1356 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1357 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1358 }
1359
1360 LOCK_SQLITE()
1361 if ((*object_id != CK_INVALID_HANDLE0) &&
1362 !sdb_objectExists(sdb, *object_id)) {
1363 this_object = *object_id;
1364 } else {
1365 this_object = sdb_getObjectId(sdb);
1366 }
1367 if (this_object == CK_INVALID_HANDLE0) {
1368 UNLOCK_SQLITE();
1369 return CKR_HOST_MEMORY0x00000002UL;
1370 }
1371 columnStr = sqlite3_mprintf("");
1372 valueStr = sqlite3_mprintf("");
1373 *object_id = this_object;
1374 for (i = 0; columnStr && valueStr && i < count; i++) {
1375 newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type);
1376 sqlite3_free(columnStr);
1377 columnStr = newStr;
1378 newStr = sqlite3_mprintf("%s,$VALUE%d", valueStr, i);
1379 sqlite3_free(valueStr);
1380 valueStr = newStr;
1381 }
1382 newStr = NULL((void*)0);
1383 if ((columnStr == NULL((void*)0)) || (valueStr == NULL((void*)0))) {
1384 if (columnStr) {
1385 sqlite3_free(columnStr);
1386 }
1387 if (valueStr) {
1388 sqlite3_free(valueStr);
1389 }
1390 UNLOCK_SQLITE()
1391 return CKR_HOST_MEMORY0x00000002UL;
1392 }
1393 newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr);
1394 sqlite3_free(columnStr);
1395 sqlite3_free(valueStr);
1396 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1397 if (error != CKR_OK0x00000000UL) {
1398 goto loser;
1399 }
1400 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1401 if (sqlerr != SQLITE_OK0)
1402 goto loser;
1403 sqlerr = sqlite3_bind_int(stmt, 1, *object_id);
1404 if (sqlerr != SQLITE_OK0)
1405 goto loser;
1406 for (i = 0; i < count; i++) {
1407 if (template[i].ulValueLen) {
1408 sqlerr = sqlite3_bind_blob(stmt, i + 2, template[i].pValue,
1409 template[i].ulValueLen, SQLITE_STATIC((sqlite3_destructor_type)0));
1410 } else {
1411 sqlerr = sqlite3_bind_blob(stmt, i + 2, SQLITE_EXPLICIT_NULL,
1412 SQLITE_EXPLICIT_NULL_LEN3, SQLITE_STATIC((sqlite3_destructor_type)0));
1413 }
1414 if (sqlerr != SQLITE_OK0)
1415 goto loser;
1416 }
1417
1418 do {
1419 sqlerr = sqlite3_step(stmt);
1420 if (sqlerr == SQLITE_BUSY5) {
1421 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1422 }
1423 } while (!sdb_done(sqlerr, &retry));
1424
1425loser:
1426 if (newStr) {
1427 sqlite3_free(newStr);
1428 }
1429 if (error == CKR_OK0x00000000UL) {
1430 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1431 }
1432
1433 if (stmt) {
1434 sqlite3_reset(stmt);
1435 sqlite3_finalize(stmt);
1436 }
1437
1438 if (sqlDB) {
1439 sdb_closeDBLocal(sdb_p, sqlDB);
1440 }
1441 UNLOCK_SQLITE()
1442
1443 return error;
1444}
1445
1446/*
1447 * Generic destroy that can destroy metadata or objects
1448 */
1449static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);";
1450CK_RV
1451sdb_destroyAnyObject(SDB *sdb, const char *table,
1452 CK_OBJECT_HANDLE object_id, const char *string_id)
1453{
1454 SDBPrivate *sdb_p = sdb->private;
1455 sqlite3 *sqlDB = NULL((void*)0);
1456 sqlite3_stmt *stmt = NULL((void*)0);
1457 char *newStr = NULL((void*)0);
1458 int sqlerr = SQLITE_OK0;
1459 CK_RV error = CKR_OK0x00000000UL;
1460 int retry = 0;
1461
1462 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1463 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1464 }
1465
1466 LOCK_SQLITE()
1467 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1468 if (error != CKR_OK0x00000000UL) {
1469 goto loser;
1470 }
1471 newStr = sqlite3_mprintf(DESTROY_CMD, table);
1472 if (newStr == NULL((void*)0)) {
1473 error = CKR_HOST_MEMORY0x00000002UL;
1474 goto loser;
1475 }
1476 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
1477 sqlite3_free(newStr);
1478 if (sqlerr != SQLITE_OK0)
1479 goto loser;
1480 if (string_id == NULL((void*)0)) {
1481 sqlerr = sqlite3_bind_int(stmt, 1, object_id);
1482 } else {
1483 sqlerr = sqlite3_bind_text(stmt, 1, string_id,
1484 PORT_Strlen(string_id)strlen(string_id), SQLITE_STATIC((sqlite3_destructor_type)0));
1485 }
1486 if (sqlerr != SQLITE_OK0)
1487 goto loser;
1488
1489 do {
1490 sqlerr = sqlite3_step(stmt);
1491 if (sqlerr == SQLITE_BUSY5) {
1492 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1493 }
1494 } while (!sdb_done(sqlerr, &retry));
1495
1496loser:
1497 if (error == CKR_OK0x00000000UL) {
1498 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1499 }
1500
1501 if (stmt) {
1502 sqlite3_reset(stmt);
1503 sqlite3_finalize(stmt);
1504 }
1505
1506 if (sqlDB) {
1507 sdb_closeDBLocal(sdb_p, sqlDB);
1508 }
1509
1510 UNLOCK_SQLITE()
1511 return error;
1512}
1513
1514CK_RV
1515sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
1516{
1517 SDBPrivate *sdb_p = sdb->private;
1518 return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL((void*)0));
1519}
1520
1521CK_RV
1522sdb_DestroyMetaData(SDB *sdb, const char *id)
1523{
1524 return sdb_destroyAnyObject(sdb, "metaData", 0, id);
1525}
1526
1527static const char BEGIN_CMD[] = "BEGIN IMMEDIATE TRANSACTION;";
1528
1529/*
1530 * start a transaction.
1531 *
1532 * We need to open a new database, then store that new database into
1533 * the private data structure. We open the database first, then use locks
1534 * to protect storing the data to prevent deadlocks.
1535 */
1536CK_RV
1537sdb_Begin(SDB *sdb)
1538{
1539 SDBPrivate *sdb_p = sdb->private;
1540 sqlite3 *sqlDB = NULL((void*)0);
1541 sqlite3_stmt *stmt = NULL((void*)0);
1542 int sqlerr = SQLITE_OK0;
1543 CK_RV error = CKR_OK0x00000000UL;
1544 int retry = 0;
1545
1546 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1547 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1548 }
1549
1550 LOCK_SQLITE()
1551
1552 /* get a new version that we will use for the entire transaction */
1553 sqlerr = sdb_openDB(sdb_p->sqlDBName, &sqlDB, SDB_RDWR2);
1554 if (sqlerr != SQLITE_OK0) {
1555 goto loser;
1556 }
1557
1558 sqlerr = sqlite3_prepare_v2(sqlDB, BEGIN_CMD, -1, &stmt, NULL((void*)0));
1559
1560 do {
1561 sqlerr = sqlite3_step(stmt);
1562 if (sqlerr == SQLITE_BUSY5) {
1563 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1564 }
1565 /* don't retry BEGIN transaction*/
1566 retry = 0;
1567 } while (!sdb_done(sqlerr, &retry));
1568
1569 if (stmt) {
1570 sqlite3_reset(stmt);
1571 sqlite3_finalize(stmt);
1572 }
1573
1574loser:
1575 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1576
1577 /* we are starting a new transaction,
1578 * and if we succeeded, then save this database for the rest of
1579 * our transaction */
1580 if (error == CKR_OK0x00000000UL) {
1581 /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point
1582 * sdb_p->sqlXactDB MUST be null */
1583 PR_EnterMonitor(sdb_p->dbMon);
1584 PORT_Assert(sdb_p->sqlXactDB == NULL)((sdb_p->sqlXactDB == ((void*)0)) ? ((void)0) : PR_Assert(
"sdb_p->sqlXactDB == NULL", "/root/firefox-clang/security/nss/lib/softoken/sdb.c"
, 1584))
;
1585 sdb_p->sqlXactDB = sqlDB;
1586 sdb_p->sqlXactThread = PR_GetCurrentThread();
1587 PR_ExitMonitor(sdb_p->dbMon);
1588 } else {
1589 /* we failed to start our transaction,
1590 * free any databases we opened. */
1591 if (sqlDB) {
1592 sqlite3_close(sqlDB);
1593 }
1594 }
1595
1596 UNLOCK_SQLITE()
1597 return error;
1598}
1599
1600/*
1601 * Complete a transaction. Basically undo everything we did in begin.
1602 * There are 2 flavors Abort and Commit. Basically the only differerence between
1603 * these 2 are what the database will show. (no change in to former, change in
1604 * the latter).
1605 */
1606static CK_RV
1607sdb_complete(SDB *sdb, const char *cmd)
1608{
1609 SDBPrivate *sdb_p = sdb->private;
1610 sqlite3 *sqlDB = NULL((void*)0);
1611 sqlite3_stmt *stmt = NULL((void*)0);
1612 int sqlerr = SQLITE_OK0;
1613 CK_RV error = CKR_OK0x00000000UL;
1614 int retry = 0;
1615
1616 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1617 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1618 }
1619
1620 /* We must have a transation database, or we shouldn't have arrived here */
1621 PR_EnterMonitor(sdb_p->dbMon);
1622 PORT_Assert(sdb_p->sqlXactDB)((sdb_p->sqlXactDB) ? ((void)0) : PR_Assert("sdb_p->sqlXactDB"
, "/root/firefox-clang/security/nss/lib/softoken/sdb.c", 1622
))
;
1623 if (sdb_p->sqlXactDB == NULL((void*)0)) {
1624 PR_ExitMonitor(sdb_p->dbMon);
1625 return CKR_GENERAL_ERROR0x00000005UL; /* shouldn't happen */
1626 }
1627 PORT_Assert(sdb_p->sqlXactThread == PR_GetCurrentThread())((sdb_p->sqlXactThread == PR_GetCurrentThread()) ? ((void)
0) : PR_Assert("sdb_p->sqlXactThread == PR_GetCurrentThread()"
, "/root/firefox-clang/security/nss/lib/softoken/sdb.c", 1627
))
;
1628 if (sdb_p->sqlXactThread != PR_GetCurrentThread()) {
1629 PR_ExitMonitor(sdb_p->dbMon);
1630 return CKR_GENERAL_ERROR0x00000005UL; /* shouldn't happen */
1631 }
1632 sqlDB = sdb_p->sqlXactDB;
1633 sdb_p->sqlXactDB = NULL((void*)0); /* no one else can get to this DB,
1634 * safe to unlock */
1635 sdb_p->sqlXactThread = NULL((void*)0);
1636 PR_ExitMonitor(sdb_p->dbMon);
1637
1638 sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL((void*)0));
Value stored to 'sqlerr' is never read
1639
1640 do {
1641 sqlerr = sqlite3_step(stmt);
1642 if (sqlerr == SQLITE_BUSY5) {
1643 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1644 }
1645 } while (!sdb_done(sqlerr, &retry));
1646
1647 /* Pending BEGIN TRANSACTIONS Can move forward at this point. */
1648
1649 if (stmt) {
1650 sqlite3_reset(stmt);
1651 sqlite3_finalize(stmt);
1652 }
1653
1654 /* we we have a cached DB image, update it as well */
1655 if (sdb_p->cacheTable) {
1656 PR_EnterMonitor(sdb_p->dbMon);
1657 sdb_updateCache(sdb_p);
1658 PR_ExitMonitor(sdb_p->dbMon);
1659 }
1660
1661 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1662
1663 /* We just finished a transaction.
1664 * Free the database, and remove it from the list */
1665 sqlite3_close(sqlDB);
1666
1667 return error;
1668}
1669
1670static const char COMMIT_CMD[] = "COMMIT TRANSACTION;";
1671CK_RV
1672sdb_Commit(SDB *sdb)
1673{
1674 CK_RV crv;
1675 LOCK_SQLITE()
1676 crv = sdb_complete(sdb, COMMIT_CMD);
1677 UNLOCK_SQLITE()
1678 return crv;
1679}
1680
1681static const char ROLLBACK_CMD[] = "ROLLBACK TRANSACTION;";
1682CK_RV
1683sdb_Abort(SDB *sdb)
1684{
1685 CK_RV crv;
1686 LOCK_SQLITE()
1687 crv = sdb_complete(sdb, ROLLBACK_CMD);
1688 UNLOCK_SQLITE()
1689 return crv;
1690}
1691
1692static int tableExists(sqlite3 *sqlDB, const char *tableName);
1693
1694static const char GET_PW_CMD[] = "SELECT ALL * FROM metaData WHERE id=$ID LIMIT 1;";
1695CK_RV
1696sdb_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2)
1697{
1698 SDBPrivate *sdb_p = sdb->private;
1699 sqlite3 *sqlDB = NULL((void*)0);
1700 sqlite3_stmt *stmt = NULL((void*)0);
1701 int sqlerr = SQLITE_OK0;
1702 CK_RV error = CKR_OK0x00000000UL;
1703 int found = 0;
1704 int retry = 0;
1705
1706 LOCK_SQLITE()
1707 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1708 if (error != CKR_OK0x00000000UL) {
1709 goto loser;
1710 }
1711
1712 /* handle 'test' versions of the sqlite db */
1713 sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL((void*)0));
1714 /* Sigh, if we created a new table since we opened the database,
1715 * the database handle will not see the new table, we need to close this
1716 * database and reopen it. This is safe because we are holding the lock
1717 * still. */
1718 if (sqlerr == SQLITE_SCHEMA17) {
1719 sqlerr = sdb_reopenDBLocal(sdb_p, &sqlDB);
1720 if (sqlerr != SQLITE_OK0) {
1721 goto loser;
1722 }
1723 sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL((void*)0));
1724 }
1725 if (sqlerr != SQLITE_OK0)
1726 goto loser;
1727 sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id)strlen(id), SQLITE_STATIC((sqlite3_destructor_type)0));
1728 do {
1729 sqlerr = sqlite3_step(stmt);
1730 if (sqlerr == SQLITE_BUSY5) {
1731 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1732 }
1733 if (sqlerr == SQLITE_ROW100) {
1734 const char *blobData;
1735 unsigned int len = item1->len;
1736 item1->len = sqlite3_column_bytes(stmt, 1);
1737 if (item1->len > len) {
1738 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1739 goto loser;
1740 }
1741 blobData = sqlite3_column_blob(stmt, 1);
1742 PORT_Memcpymemcpy(item1->data, blobData, item1->len);
1743 if (item2) {
1744 len = item2->len;
1745 item2->len = sqlite3_column_bytes(stmt, 2);
1746 if (item2->len > len) {
1747 error = CKR_BUFFER_TOO_SMALL0x00000150UL;
1748 goto loser;
1749 }
1750 blobData = sqlite3_column_blob(stmt, 2);
1751 PORT_Memcpymemcpy(item2->data, blobData, item2->len);
1752 }
1753 found = 1;
1754 }
1755 } while (!sdb_done(sqlerr, &retry));
1756
1757loser:
1758 /* fix up the error if necessary */
1759 if (error == CKR_OK0x00000000UL) {
1760 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1761 if (!found && error == CKR_OK0x00000000UL) {
1762 error = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1763 }
1764 }
1765
1766 if (stmt) {
1767 sqlite3_reset(stmt);
1768 sqlite3_finalize(stmt);
1769 }
1770
1771 if (sqlDB) {
1772 sdb_closeDBLocal(sdb_p, sqlDB);
1773 }
1774 UNLOCK_SQLITE()
1775
1776 return error;
1777}
1778
1779static const char PW_CREATE_TABLE_CMD[] =
1780 "CREATE TABLE metaData (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, item1, item2);";
1781static const char PW_CREATE_CMD[] =
1782 "INSERT INTO metaData (id,item1,item2) VALUES($ID,$ITEM1,$ITEM2);";
1783static const char MD_CREATE_CMD[] =
1784 "INSERT INTO metaData (id,item1) VALUES($ID,$ITEM1);";
1785
1786CK_RV
1787sdb_PutMetaData(SDB *sdb, const char *id, const SECItem *item1,
1788 const SECItem *item2)
1789{
1790 SDBPrivate *sdb_p = sdb->private;
1791 sqlite3 *sqlDB = sdb_p->sqlXactDB;
1792 sqlite3_stmt *stmt = NULL((void*)0);
1793 int sqlerr = SQLITE_OK0;
1794 CK_RV error = CKR_OK0x00000000UL;
1795 int retry = 0;
1796 const char *cmd = PW_CREATE_CMD;
1797
1798 if ((sdb->sdb_flags & SDB_RDONLY1) != 0) {
1799 return CKR_TOKEN_WRITE_PROTECTED0x000000E2UL;
1800 }
1801
1802 LOCK_SQLITE()
1803 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1804 if (error != CKR_OK0x00000000UL) {
1805 goto loser;
1806 }
1807
1808 if (!tableExists(sqlDB, "metaData")) {
1809 sqlerr = sqlite3_exec(sqlDB, PW_CREATE_TABLE_CMD, NULL((void*)0), 0, NULL((void*)0));
1810 if (sqlerr != SQLITE_OK0)
1811 goto loser;
1812 }
1813 if (item2 == NULL((void*)0)) {
1814 cmd = MD_CREATE_CMD;
1815 }
1816 sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL((void*)0));
1817 if (sqlerr != SQLITE_OK0)
1818 goto loser;
1819 sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id)strlen(id), SQLITE_STATIC((sqlite3_destructor_type)0));
1820 if (sqlerr != SQLITE_OK0)
1821 goto loser;
1822 sqlerr = sqlite3_bind_blob(stmt, 2, item1->data, item1->len, SQLITE_STATIC((sqlite3_destructor_type)0));
1823 if (sqlerr != SQLITE_OK0)
1824 goto loser;
1825 if (item2) {
1826 sqlerr = sqlite3_bind_blob(stmt, 3, item2->data,
1827 item2->len, SQLITE_STATIC((sqlite3_destructor_type)0));
1828 if (sqlerr != SQLITE_OK0)
1829 goto loser;
1830 }
1831
1832 do {
1833 sqlerr = sqlite3_step(stmt);
1834 if (sqlerr == SQLITE_BUSY5) {
1835 PR_Sleep(SDB_BUSY_RETRY_TIME5);
1836 }
1837 } while (!sdb_done(sqlerr, &retry));
1838
1839loser:
1840 /* fix up the error if necessary */
1841 if (error == CKR_OK0x00000000UL) {
1842 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1843 }
1844
1845 if (stmt) {
1846 sqlite3_reset(stmt);
1847 sqlite3_finalize(stmt);
1848 }
1849
1850 if (sqlDB) {
1851 sdb_closeDBLocal(sdb_p, sqlDB);
1852 }
1853 UNLOCK_SQLITE()
1854
1855 return error;
1856}
1857
1858static const char RESET_CMD[] = "DELETE FROM %s;";
1859CK_RV
1860sdb_Reset(SDB *sdb)
1861{
1862 SDBPrivate *sdb_p = sdb->private;
1863 sqlite3 *sqlDB = NULL((void*)0);
1864 char *newStr;
1865 int sqlerr = SQLITE_OK0;
1866 CK_RV error = CKR_OK0x00000000UL;
1867
1868 /* only Key databases can be reset */
1869 if (sdb_p->type != SDB_KEY) {
1870 return CKR_OBJECT_HANDLE_INVALID0x00000082UL;
1871 }
1872
1873 LOCK_SQLITE()
1874 error = sdb_openDBLocal(sdb_p, &sqlDB, NULL((void*)0));
1875 if (error != CKR_OK0x00000000UL) {
1876 goto loser;
1877 }
1878
1879 if (tableExists(sqlDB, sdb_p->table)) {
1880 /* delete the contents of the key table */
1881 newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
1882 if (newStr == NULL((void*)0)) {
1883 error = CKR_HOST_MEMORY0x00000002UL;
1884 goto loser;
1885 }
1886 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
1887 sqlite3_free(newStr);
1888
1889 if (sqlerr != SQLITE_OK0)
1890 goto loser;
1891 }
1892
1893 /* delete the password entry table */
1894 sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;",
1895 NULL((void*)0), 0, NULL((void*)0));
1896
1897loser:
1898 /* fix up the error if necessary */
1899 if (error == CKR_OK0x00000000UL) {
1900 error = sdb_mapSQLError(sdb_p->type, sqlerr);
1901 }
1902
1903 if (sqlDB) {
1904 sdb_closeDBLocal(sdb_p, sqlDB);
1905 }
1906
1907 UNLOCK_SQLITE()
1908 return error;
1909}
1910
1911CK_RV
1912sdb_Close(SDB *sdb)
1913{
1914 SDBPrivate *sdb_p = sdb->private;
1915 int sqlerr = SQLITE_OK0;
1916 sdbDataType type = sdb_p->type;
1917
1918 sqlerr = sqlite3_close(sdb_p->sqlReadDB);
1919 PORT_FreePORT_Free_Util(sdb_p->sqlDBName);
1920 if (sdb_p->cacheTable) {
1921 sqlite3_free(sdb_p->cacheTable);
1922 }
1923 if (sdb_p->dbMon) {
1924 PR_DestroyMonitor(sdb_p->dbMon);
1925 }
1926 free(sdb_p->schemaAttrs);
1927 free(sdb_p);
1928 free(sdb);
1929 return sdb_mapSQLError(type, sqlerr);
1930}
1931
1932/*
1933 * functions to support open
1934 */
1935
1936static const char CHECK_TABLE_CMD[] = "SELECT ALL * FROM %s LIMIT 0;";
1937
1938/* return 1 if sqlDB contains table 'tableName */
1939static int
1940tableExists(sqlite3 *sqlDB, const char *tableName)
1941{
1942 char *cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
1943 int sqlerr = SQLITE_OK0;
1944
1945 if (cmd == NULL((void*)0)) {
1946 return 0;
1947 }
1948
1949 sqlerr = sqlite3_exec(sqlDB, cmd, NULL((void*)0), 0, 0);
1950 sqlite3_free(cmd);
1951
1952 return (sqlerr == SQLITE_OK0) ? 1 : 0;
1953}
1954
1955void
1956sdb_SetForkState(PRBool forked)
1957{
1958 /* XXXright now this is a no-op. The global fork state in the softokn3
1959 * shared library is already taken care of at the PKCS#11 level.
1960 * If and when we add fork state to the sqlite shared library and extern
1961 * interface, we will need to set it and reset it from here */
1962}
1963
1964static int
1965sdb_attributeComparator(const void *a, const void *b)
1966{
1967 if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) {
1968 return -1;
1969 }
1970 if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) {
1971 return 1;
1972 }
1973 return 0;
1974}
1975
1976static const char ADD_COLUMN_CMD[] = "ALTER TABLE %s ADD COLUMN %s";
1977static CK_RV
1978sdb_add_column(sqlite3 *sqlDB, const char *table, sdbDataType type,
1979 const char *typeString)
1980{
1981 char *newStr = sqlite3_mprintf(ADD_COLUMN_CMD, table, typeString);
1982 int sqlerr;
1983
1984 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
1985 sqlite3_free(newStr);
1986 if (sqlerr != SQLITE_OK0) {
1987 return sdb_mapSQLError(type, sqlerr);
1988 }
1989 return CKR_OK0x00000000UL;
1990}
1991
1992static const char COLUMN_QUERY_CMD[] =
1993 "SELECT * FROM %s";
1994/*
1995 * if our current database does not have all the attributes in the columns,
1996 * we need to add those columns or attempts to add objects with those
1997 * attributes will fail. We only need this on R/W databases because we only
1998 * add objects to R/W databases.
1999 */
2000static CK_RV
2001sdb_update_column(sqlite3 *sqlDB, const char *table, sdbDataType type)
2002{
2003 char *newStr = sqlite3_mprintf(COLUMN_QUERY_CMD, table);
2004 sqlite3_stmt *stmt;
2005 int columnCount;
2006 int sqlerr;
2007 CK_RV error;
2008
2009 if (!newStr) {
2010 return CKR_HOST_MEMORY0x00000002UL;
2011 }
2012
2013 sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL((void*)0));
2014 sqlite3_free(newStr);
2015 if (sqlerr != SQLITE_OK0) {
2016 return sdb_mapSQLError(type, sqlerr);
2017 }
2018
2019 columnCount = sqlite3_column_count(stmt);
2020 /* columns include the first column, which is id, which is not
2021 * and attribute. check to make sure we have at least as many attributes
2022 * as there are id in out list. This assumes we never add some
2023 * attributes in some NSS version and not others, which is generally
2024 * true. */
2025 if (columnCount >= sftkdb_known_attributes_size + 1) {
2026 sqlite3_finalize(stmt);
2027 return CKR_OK0x00000000UL;
2028 }
2029 /* we have more attributes than in the database, so we know things
2030 * are missing, find what was missing */
2031 for (size_t i = 0; i < sftkdb_known_attributes_size; i++) {
2032 char *typeString = sqlite3_mprintf("a%lx", sftkdb_known_attributes[i]);
2033 PRBool found = PR_FALSE0;
2034 /* this one index is important, we skip the first column (id), since
2035 * it will never match, starting at zero isn't a bug,
2036 * just inefficient */
2037 for (int j = 1; j < columnCount; j++) {
2038 const char *columnName = sqlite3_column_name(stmt, j);
2039 if (columnName == NULL((void*)0)) {
2040 sqlite3_free(typeString);
2041 sqlite3_finalize(stmt);
2042 /* if we couldnt' get the colmun name, it's only because
2043 * we couldn't get the memory */
2044 return CKR_HOST_MEMORY0x00000002UL;
2045 }
2046 if (PORT_Strcmpstrcmp(typeString, columnName) == 0) {
2047 /* we found this one, no need to add it */
2048 found = PR_TRUE1;
2049 break;
2050 }
2051 }
2052 if (found) {
2053 sqlite3_free(typeString);
2054 continue;
2055 }
2056 /* we didn't find the attribute, so now add it */
2057 error = sdb_add_column(sqlDB, table, type, typeString);
2058 if (error != CKR_OK0x00000000UL) {
2059 sqlite3_free(typeString);
2060 sqlite3_finalize(stmt);
2061 return error;
2062 }
2063 sqlite3_free(typeString);
2064 }
2065 sqlite3_finalize(stmt);
2066 return CKR_OK0x00000000UL;
2067}
2068
2069/*
2070 * initialize a single database
2071 */
2072static const char INIT_CMD[] =
2073 "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)";
2074
2075CK_RV
2076sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
2077 int *newInit, int inFlags, PRUint32 accessOps, SDB **pSdb)
2078{
2079 char *initStr = NULL((void*)0);
2080 char *newStr;
2081 char *queryStr = NULL((void*)0);
2082 int inTransaction = 0;
2083 SDB *sdb = NULL((void*)0);
2084 SDBPrivate *sdb_p = NULL((void*)0);
2085 sqlite3 *sqlDB = NULL((void*)0);
2086 int sqlerr = SQLITE_OK0;
2087 CK_RV error = CKR_OK0x00000000UL;
2088 char *cacheTable = NULL((void*)0);
2089 PRIntervalTime now = 0;
2090 char *env;
2091 PRBool enableCache = PR_FALSE0;
2092 PRBool checkFSType = PR_FALSE0;
2093 PRBool measureSpeed = PR_FALSE0;
2094 PRBool create;
2095 int flags = inFlags & 0x7;
2096
2097 *pSdb = NULL((void*)0);
2098 *inUpdate = 0;
2099
2100 /* sqlite3 doesn't have a flag to specify that we want to
2101 * open the database read only. If the db doesn't exist,
2102 * sqlite3 will always create it.
2103 */
2104 LOCK_SQLITE();
2105 create = (_NSSUTIL_Access(dbname, PR_ACCESS_EXISTS)PR_Access((dbname), (PR_ACCESS_EXISTS)) != PR_SUCCESS);
2106 if ((flags == SDB_RDONLY1) && create) {
2107 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2108 goto loser;
2109 }
2110 sqlerr = sdb_openDB(dbname, &sqlDB, flags);
2111 if (sqlerr != SQLITE_OK0) {
2112 error = sdb_mapSQLError(type, sqlerr);
2113 goto loser;
2114 }
2115
2116 /*
2117 * SQL created the file, but it doesn't set appropriate modes for
2118 * a database.
2119 *
2120 * NO NSPR call for chmod? :(
2121 */
2122 if (create && sdb_chmod(dbname, 0600)chmod((dbname), (0600)) != 0) {
2123 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2124 goto loser;
2125 }
2126
2127 if (flags != SDB_RDONLY1) {
2128 sqlerr = sqlite3_exec(sqlDB, BEGIN_CMD, NULL((void*)0), 0, NULL((void*)0));
2129 if (sqlerr != SQLITE_OK0) {
2130 error = sdb_mapSQLError(type, sqlerr);
2131 goto loser;
2132 }
2133 inTransaction = 1;
2134 }
2135 if (!tableExists(sqlDB, table)) {
2136 *newInit = 1;
2137 if (flags != SDB_CREATE4) {
2138 error = sdb_mapSQLError(type, SQLITE_CANTOPEN14);
2139 goto loser;
2140 }
2141 initStr = sqlite3_mprintf("");
2142 for (size_t i = 0; initStr && i < sftkdb_known_attributes_size; i++) {
2143 newStr = sqlite3_mprintf("%s, a%lx", initStr,
2144 sftkdb_known_attributes[i]);
2145 sqlite3_free(initStr);
2146 initStr = newStr;
2147 }
2148 if (initStr == NULL((void*)0)) {
2149 error = CKR_HOST_MEMORY0x00000002UL;
2150 goto loser;
2151 }
2152
2153 newStr = sqlite3_mprintf(INIT_CMD, table, initStr);
2154 sqlite3_free(initStr);
2155 if (newStr == NULL((void*)0)) {
2156 error = CKR_HOST_MEMORY0x00000002UL;
2157 goto loser;
2158 }
2159 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2160 sqlite3_free(newStr);
2161 if (sqlerr != SQLITE_OK0) {
2162 error = sdb_mapSQLError(type, sqlerr);
2163 goto loser;
2164 }
2165
2166 newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, table);
2167 if (newStr == NULL((void*)0)) {
2168 error = CKR_HOST_MEMORY0x00000002UL;
2169 goto loser;
2170 }
2171 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2172 sqlite3_free(newStr);
2173 if (sqlerr != SQLITE_OK0) {
2174 error = sdb_mapSQLError(type, sqlerr);
2175 goto loser;
2176 }
2177
2178 newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, table);
2179 if (newStr == NULL((void*)0)) {
2180 error = CKR_HOST_MEMORY0x00000002UL;
2181 goto loser;
2182 }
2183 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2184 sqlite3_free(newStr);
2185 if (sqlerr != SQLITE_OK0) {
2186 error = sdb_mapSQLError(type, sqlerr);
2187 goto loser;
2188 }
2189
2190 newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, table);
2191 if (newStr == NULL((void*)0)) {
2192 error = CKR_HOST_MEMORY0x00000002UL;
2193 goto loser;
2194 }
2195 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2196 sqlite3_free(newStr);
2197 if (sqlerr != SQLITE_OK0) {
2198 error = sdb_mapSQLError(type, sqlerr);
2199 goto loser;
2200 }
2201
2202 newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, table);
2203 if (newStr == NULL((void*)0)) {
2204 error = CKR_HOST_MEMORY0x00000002UL;
2205 goto loser;
2206 }
2207 sqlerr = sqlite3_exec(sqlDB, newStr, NULL((void*)0), 0, NULL((void*)0));
2208 sqlite3_free(newStr);
2209 if (sqlerr != SQLITE_OK0) {
2210 error = sdb_mapSQLError(type, sqlerr);
2211 goto loser;
2212 }
2213 } else if (flags != SDB_RDONLY1) {
2214 /* check to see if we need to update the scheme, only need to
2215 * do this if we open r/w, since that's the only case where
2216 * it's a problem if the attribute colmumn are missing */
2217 error = sdb_update_column(sqlDB, table, type);
2218 if (error != CKR_OK0x00000000UL) {
2219 goto loser;
2220 }
2221 }
2222
2223 /*
2224 * detect the case where we have created the database, but have
2225 * not yet updated it.
2226 *
2227 * We only check the Key database because only the key database has
2228 * a metaData table. The metaData table is created when a password
2229 * is set, or in the case of update, when a password is supplied.
2230 * If no key database exists, then the update would have happened immediately
2231 * on noticing that the cert database didn't exist (see newInit set above).
2232 */
2233 if (type == SDB_KEY && !tableExists(sqlDB, "metaData")) {
2234 *newInit = 1;
2235 }
2236
2237 /* access to network filesystems are significantly slower than local ones
2238 * for database operations. In those cases we need to create a cached copy
2239 * of the database in a temporary location on the local disk. SQLITE
2240 * already provides a way to create a temporary table and initialize it,
2241 * so we use it for the cache (see sdb_buildCache for how it's done).*/
2242
2243 /*
2244 * we decide whether or not to use the cache based on the following input.
2245 *
2246 * NSS_SDB_USE_CACHE environment variable is set to anything other than
2247 * "yes" or "no" (for instance, "auto"): NSS will measure the performance
2248 * of access to the temp database versus the access to the user's
2249 * passed-in database location. If the temp database location is
2250 * "significantly" faster we will use the cache.
2251 *
2252 * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no":
2253 * cache will not be used.
2254 *
2255 * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will
2256 * always be used.
2257 *
2258 * It is expected that most applications will not need this feature, and
2259 * thus it is disabled by default.
2260 */
2261
2262 env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
2263
2264 /* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default,
2265 * which is the expected behavior for NSS_SDB_USE_CACHE="no".
2266 * We don't need to check for "no" here. */
2267 if (!env) {
2268 /* By default, with no variable set, we avoid expensive measuring for
2269 * most FS types. We start with inexpensive FS type checking, and
2270 * might perform measuring for some types. */
2271 checkFSType = PR_TRUE1;
2272 } else if (PORT_StrcasecmpPL_strcasecmp(env, "yes") == 0) {
2273 enableCache = PR_TRUE1;
2274 } else if (PORT_StrcasecmpPL_strcasecmp(env, "no") != 0) { /* not "no" => "auto" */
2275 measureSpeed = PR_TRUE1;
2276 }
2277
2278 if (checkFSType) {
2279#if defined(LINUX1) && !defined(ANDROID)
2280 struct statfs statfs_s;
2281 if (statfs(dbname, &statfs_s) == 0) {
2282 switch (statfs_s.f_type) {
2283 case SMB_SUPER_MAGIC0x517B:
2284 case 0xff534d42: /* CIFS_MAGIC_NUMBER */
2285 case NFS_SUPER_MAGIC0x6969:
2286 /* We assume these are slow. */
2287 enableCache = PR_TRUE1;
2288 break;
2289 case CODA_SUPER_MAGIC0x73757245:
2290 case 0x65735546: /* FUSE_SUPER_MAGIC */
2291 case NCP_SUPER_MAGIC0x564c:
2292 /* It's uncertain if this FS is fast or slow.
2293 * It seems reasonable to perform slow measuring for users
2294 * with questionable FS speed. */
2295 measureSpeed = PR_TRUE1;
2296 break;
2297 case AFS_SUPER_MAGIC0x5346414F: /* Already implements caching. */
2298 default:
2299 break;
2300 }
2301 }
2302#endif
2303 }
2304
2305 if (measureSpeed) {
2306 char *tempDir = NULL((void*)0);
2307 PRUint32 tempOps = 0;
2308 /*
2309 * Use PR_Access to determine how expensive it
2310 * is to check for the existance of a local file compared to the same
2311 * check in the temp directory. If the temp directory is faster, cache
2312 * the database there. */
2313 tempDir = sdb_getTempDir(sqlDB);
2314 if (tempDir) {
2315 tempOps = sdb_measureAccess(tempDir);
2316 PORT_FreePORT_Free_Util(tempDir);
2317
2318 /* There is a cost to continually copying the database.
2319 * Account for that cost with the arbitrary factor of 10 */
2320 enableCache = (PRBool)(tempOps > accessOps * 10);
2321 }
2322 }
2323
2324 if (enableCache) {
2325 /* try to set the temp store to memory.*/
2326 sqlite3_exec(sqlDB, "PRAGMA temp_store=MEMORY", NULL((void*)0), 0, NULL((void*)0));
2327 /* Failure to set the temp store to memory is not fatal,
2328 * ignore the error */
2329
2330 cacheTable = sqlite3_mprintf("%sCache", table);
2331 if (cacheTable == NULL((void*)0)) {
2332 error = CKR_HOST_MEMORY0x00000002UL;
2333 goto loser;
2334 }
2335 /* build the cache table */
2336 error = sdb_buildCache(sqlDB, type, cacheTable, table);
2337 if (error != CKR_OK0x00000000UL) {
2338 goto loser;
2339 }
2340 /* initialize the last cache build time */
2341 now = PR_IntervalNow();
2342 }
2343
2344 sdb = (SDB *)malloc(sizeof(SDB));
2345 if (!sdb) {
2346 error = CKR_HOST_MEMORY0x00000002UL;
2347 goto loser;
2348 }
2349 sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate));
2350 if (!sdb_p) {
2351 error = CKR_HOST_MEMORY0x00000002UL;
2352 goto loser;
2353 }
2354
2355 /* Cache the attributes that are held in the table, so we can later check
2356 * that queried attributes actually exist. We don't assume the schema
2357 * to be exactly |sftkdb_known_attributes|, as it may change over time. */
2358 sdb_p->schemaAttrs = NULL((void*)0);
2359 if (!PORT_Strcmpstrcmp("nssPublic", table) ||
2360 !PORT_Strcmpstrcmp("nssPrivate", table)) {
2361 sqlite3_stmt *stmt = NULL((void*)0);
2362 int retry = 0;
2363 unsigned int backedAttrs = 0;
2364
2365 /* Can't bind parameters to a PRAGMA. */
2366 queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table);
2367 if (queryStr == NULL((void*)0)) {
2368 error = CKR_HOST_MEMORY0x00000002UL;
2369 goto loser;
2370 }
2371 sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL((void*)0));
2372 sqlite3_free(queryStr);
2373 queryStr = NULL((void*)0);
2374 if (sqlerr != SQLITE_OK0) {
2375 goto loser;
2376 }
2377 unsigned int schemaAttrsCapacity = sftkdb_known_attributes_size;
2378 sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2379 if (!sdb_p->schemaAttrs) {
2380 error = CKR_HOST_MEMORY0x00000002UL;
2381 goto loser;
2382 }
2383 do {
2384 sqlerr = sqlite3_step(stmt);
2385 if (sqlerr == SQLITE_BUSY5) {
2386 PR_Sleep(SDB_BUSY_RETRY_TIME5);
2387 }
2388 if (sqlerr == SQLITE_ROW100) {
2389 if (backedAttrs == schemaAttrsCapacity) {
2390 schemaAttrsCapacity += sftkdb_known_attributes_size;
2391 sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs,
2392 schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
2393 if (!sdb_p->schemaAttrs) {
2394 error = CKR_HOST_MEMORY0x00000002UL;
2395 goto loser;
2396 }
2397 }
2398 /* Record the ULONG attribute value. */
2399 char *val = (char *)sqlite3_column_text(stmt, 1);
2400 if (val && val[0] == 'a') {
2401 CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL((void*)0), 16);
2402 sdb_p->schemaAttrs[backedAttrs++] = attr;
2403 }
2404 }
2405 } while (!sdb_done(sqlerr, &retry));
2406
2407 if (sqlerr != SQLITE_DONE101) {
2408 goto loser;
2409 }
2410 sqlerr = sqlite3_reset(stmt);
2411 if (sqlerr != SQLITE_OK0) {
2412 goto loser;
2413 }
2414 sqlerr = sqlite3_finalize(stmt);
2415 if (sqlerr != SQLITE_OK0) {
2416 goto loser;
2417 }
2418
2419 sdb_p->numSchemaAttrs = backedAttrs;
2420
2421 /* Sort these once so we can shortcut invalid attribute searches. */
2422 qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs,
2423 sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator);
2424 }
2425
2426 /* invariant fields */
2427 sdb_p->sqlDBName = PORT_StrdupPORT_Strdup_Util(dbname);
2428 sdb_p->type = type;
2429 sdb_p->table = table;
2430 sdb_p->cacheTable = cacheTable;
2431 sdb_p->lastUpdateTime = now;
2432 /* set the cache delay time. This is how long we will wait before we
2433 * decide the existing cache is stale. Currently set to 10 sec */
2434 sdb_p->updateInterval = PR_SecondsToInterval(10);
2435 sdb_p->dbMon = PR_NewMonitor();
2436 /* these fields are protected by the lock */
2437 sdb_p->sqlXactDB = NULL((void*)0);
2438 sdb_p->sqlXactThread = NULL((void*)0);
2439 sdb->private = sdb_p;
2440 sdb->version = 1;
2441 sdb->sdb_flags = inFlags | SDB_HAS_META8;
2442 sdb->app_private = NULL((void*)0);
2443 sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
2444 sdb->sdb_FindObjects = sdb_FindObjects;
2445 sdb->sdb_FindObjectsFinal = sdb_FindObjectsFinal;
2446 sdb->sdb_GetAttributeValue = sdb_GetAttributeValue;
2447 sdb->sdb_SetAttributeValue = sdb_SetAttributeValue;
2448 sdb->sdb_CreateObject = sdb_CreateObject;
2449 sdb->sdb_DestroyObject = sdb_DestroyObject;
2450 sdb->sdb_GetMetaData = sdb_GetMetaData;
2451 sdb->sdb_PutMetaData = sdb_PutMetaData;
2452 sdb->sdb_DestroyMetaData = sdb_DestroyMetaData;
2453 sdb->sdb_Begin = sdb_Begin;
2454 sdb->sdb_Commit = sdb_Commit;
2455 sdb->sdb_Abort = sdb_Abort;
2456 sdb->sdb_Reset = sdb_Reset;
2457 sdb->sdb_Close = sdb_Close;
2458 sdb->sdb_SetForkState = sdb_SetForkState;
2459 sdb->sdb_GetNewObjectID = sdb_GetNewObjectID;
2460
2461 if (inTransaction) {
2462 sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL((void*)0), 0, NULL((void*)0));
2463 if (sqlerr != SQLITE_OK0) {
2464 error = sdb_mapSQLError(sdb_p->type, sqlerr);
2465 goto loser;
2466 }
2467 inTransaction = 0;
2468 }
2469
2470 sdb_p->sqlReadDB = sqlDB;
2471
2472 *pSdb = sdb;
2473 UNLOCK_SQLITE();
2474 return CKR_OK0x00000000UL;
2475
2476loser:
2477 /* lots of stuff to do */
2478 if (inTransaction) {
2479 sqlite3_exec(sqlDB, ROLLBACK_CMD, NULL((void*)0), 0, NULL((void*)0));
2480 }
2481 if (sdb) {
2482 free(sdb);
2483 }
2484 if (sdb_p) {
2485 if (sdb_p->schemaAttrs) {
2486 free(sdb_p->schemaAttrs);
2487 }
2488 free(sdb_p);
2489 }
2490 if (sqlDB) {
2491 sqlite3_close(sqlDB);
2492 }
2493 UNLOCK_SQLITE();
2494 return error;
2495}
2496
2497/* sdbopen */
2498CK_RV
2499s_open(const char *directory, const char *certPrefix, const char *keyPrefix,
2500 int cert_version, int key_version, int flags,
2501 SDB **certdb, SDB **keydb, int *newInit)
2502{
2503 char *cert = sdb_BuildFileName(directory, certPrefix,
2504 "cert", cert_version);
2505 char *key = sdb_BuildFileName(directory, keyPrefix,
2506 "key", key_version);
2507 CK_RV error = CKR_OK0x00000000UL;
2508 int inUpdate;
2509 PRUint32 accessOps;
2510
2511 if (certdb)
2512 *certdb = NULL((void*)0);
2513 if (keydb)
2514 *keydb = NULL((void*)0);
2515 *newInit = 0;
2516
2517#ifdef SQLITE_UNSAFE_THREADS
2518 if (sqlite_lock == NULL((void*)0)) {
2519 sqlite_lock = PR_NewLock();
2520 if (sqlite_lock == NULL((void*)0)) {
2521 error = CKR_HOST_MEMORY0x00000002UL;
2522 goto loser;
2523 }
2524 }
2525#endif
2526
2527 /* how long does it take to test for a non-existant file in our working
2528 * directory? Allows us to test if we may be on a network file system */
2529 accessOps = 1;
2530 {
2531 char *env;
2532 env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
2533 /* If the environment variable is undefined or set to yes or no,
2534 * sdb_init() will ignore the value of accessOps, and we can skip the
2535 * measuring.*/
2536 if (env && PORT_StrcasecmpPL_strcasecmp(env, "no") != 0 &&
2537 PORT_StrcasecmpPL_strcasecmp(env, "yes") != 0) {
2538 accessOps = sdb_measureAccess(directory);
2539 }
2540 }
2541
2542 /*
2543 * open the cert data base
2544 */
2545 if (certdb) {
2546 /* initialize Certificate database */
2547 error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate,
2548 newInit, flags, accessOps, certdb);
2549 if (error != CKR_OK0x00000000UL) {
2550 goto loser;
2551 }
2552 }
2553
2554 /*
2555 * open the key data base:
2556 * NOTE:if we want to implement a single database, we open
2557 * the same database file as the certificate here.
2558 *
2559 * cert an key db's have different tables, so they will not
2560 * conflict.
2561 */
2562 if (keydb) {
2563 /* initialize the Key database */
2564 error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate,
2565 newInit, flags, accessOps, keydb);
2566 if (error != CKR_OK0x00000000UL) {
2567 goto loser;
2568 }
2569 }
2570
2571loser:
2572 if (cert) {
2573 sqlite3_free(cert);
2574 }
2575 if (key) {
2576 sqlite3_free(key);
2577 }
2578
2579 if (error != CKR_OK0x00000000UL) {
2580 /* currently redundant, but could be necessary if more code is added
2581 * just before loser */
2582 if (keydb && *keydb) {
2583 sdb_Close(*keydb);
2584 }
2585 if (certdb && *certdb) {
2586 sdb_Close(*certdb);
2587 }
2588 }
2589
2590 return error;
2591}
2592
2593CK_RV
2594s_shutdown()
2595{
2596#ifdef SQLITE_UNSAFE_THREADS
2597 if (sqlite_lock) {
2598 PR_DestroyLock(sqlite_lock);
2599 sqlite_lock = NULL((void*)0);
2600 }
2601#endif
2602 return CKR_OK0x00000000UL;
2603}