| OLD | NEW |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 /* | 4 /* |
| 5 * This file implements PKCS 11 on top of our existing security modules | 5 * This file implements PKCS 11 on top of our existing security modules |
| 6 * | 6 * |
| 7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. | 7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. |
| 8 * This implementation has two slots: | 8 * This implementation has two slots: |
| 9 * slot 1 is our generic crypto support. It does not require login. | 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. | 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 | 11 * It can also support Private Key ops for imported Private keys. It does |
| 12 * not have any token storage. | 12 * not have any token storage. |
| 13 * slot 2 is our private key support. It requires a login before use. It | 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 | 14 * can store Private Keys and Certs as token objects. Currently only private |
| 15 * keys and their associated Certificates are saved on the token. | 15 * keys and their associated Certificates are saved on the token. |
| 16 * | 16 * |
| 17 * In this implementation, session objects are only visible to the session | 17 * In this implementation, session objects are only visible to the session |
| 18 * that created or generated them. | 18 * that created or generated them. |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 #include "sdb.h" | 21 #include "sdb.h" |
| 22 #include "pkcs11t.h" | 22 #include "pkcs11t.h" |
| 23 #include "seccomon.h" | 23 #include "seccomon.h" |
| 24 #include <sqlite3.h> | 24 #include <sqlite3.h> |
| 25 #include "prthread.h" | 25 #include "prthread.h" |
| 26 #include "prio.h" | 26 #include "prio.h" |
| 27 #include "stdio.h" | 27 #include <stdio.h> |
| 28 #include "secport.h" | 28 #include "secport.h" |
| 29 #include "prmon.h" | 29 #include "prmon.h" |
| 30 #include "prenv.h" | 30 #include "prenv.h" |
| 31 #include "prprf.h" |
| 31 #include "prsystem.h" /* for PR_GetDirectorySeparator() */ | 32 #include "prsystem.h" /* for PR_GetDirectorySeparator() */ |
| 32 #include "sys/stat.h" | 33 #include <sys/stat.h> |
| 33 #if defined (_WIN32) | 34 #if defined(_WIN32) |
| 34 #include <io.h> | 35 #include <io.h> |
| 36 #include <windows.h> |
| 37 #elif defined(XP_UNIX) |
| 38 #include <unistd.h> |
| 35 #endif | 39 #endif |
| 36 | 40 |
| 37 #ifdef SQLITE_UNSAFE_THREADS | 41 #ifdef SQLITE_UNSAFE_THREADS |
| 38 #include "prlock.h" | 42 #include "prlock.h" |
| 39 /* | 43 /* |
| 40 * SQLite can be compiled to be thread safe or not. | 44 * SQLite can be compiled to be thread safe or not. |
| 41 * turn on SQLITE_UNSAFE_THREADS if the OS does not support | 45 * turn on SQLITE_UNSAFE_THREADS if the OS does not support |
| 42 * a thread safe version of sqlite. | 46 * a thread safe version of sqlite. |
| 43 */ | 47 */ |
| 44 static PRLock *sqlite_lock = NULL; | 48 static PRLock *sqlite_lock = NULL; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 return 1; | 184 return 1; |
| 181 } | 185 } |
| 182 /* err == SQLITE_BUSY, Dont' retry forever in this case */ | 186 /* err == SQLITE_BUSY, Dont' retry forever in this case */ |
| 183 if (++(*count) >= SDB_MAX_BUSY_RETRIES) { | 187 if (++(*count) >= SDB_MAX_BUSY_RETRIES) { |
| 184 return 1; | 188 return 1; |
| 185 } | 189 } |
| 186 return 0; | 190 return 0; |
| 187 } | 191 } |
| 188 | 192 |
| 189 /* | 193 /* |
| 190 * | 194 * find out where sqlite stores the temp tables. We do this by replicating |
| 191 * strdup limited to 'n' bytes. (Note: len of file is assumed to be >= len) | 195 * the logic from sqlite. |
| 192 * | |
| 193 * We don't have a PORT_ version of this function, | |
| 194 * I suspect it's only normally available in glib, | |
| 195 */ | 196 */ |
| 197 #if defined(_WIN32) |
| 196 static char * | 198 static char * |
| 197 sdb_strndup(const char *file, int len) | 199 sdb_getFallbackTempDir(void) |
| 198 { | 200 { |
| 199 char *result = PORT_Alloc(len+1); | 201 /* sqlite uses sqlite3_temp_directory if it is not NULL. We don't have |
| 202 * access to sqlite3_temp_directory because it is not exported from |
| 203 * sqlite3.dll. Assume sqlite3_win32_set_directory isn't called and |
| 204 * sqlite3_temp_directory is NULL. |
| 205 */ |
| 206 char path[MAX_PATH]; |
| 207 DWORD rv; |
| 208 size_t len; |
| 200 | 209 |
| 201 if (result == NULL) { | 210 rv = GetTempPathA(MAX_PATH, path); |
| 202 » return result; | 211 if (rv > MAX_PATH || rv == 0) |
| 203 } | 212 return NULL; |
| 213 len = strlen(path); |
| 214 if (len == 0) |
| 215 return NULL; |
| 216 /* The returned string ends with a backslash, for example, "C:\TEMP\". */ |
| 217 if (path[len - 1] == '\\') |
| 218 path[len - 1] = '\0'; |
| 219 return PORT_Strdup(path); |
| 220 } |
| 221 #elif defined(XP_UNIX) |
| 222 static char * |
| 223 sdb_getFallbackTempDir(void) |
| 224 { |
| 225 const char *azDirs[] = { |
| 226 NULL, |
| 227 NULL, |
| 228 "/var/tmp", |
| 229 "/usr/tmp", |
| 230 "/tmp", |
| 231 NULL /* List terminator */ |
| 232 }; |
| 233 unsigned int i; |
| 234 struct stat buf; |
| 235 const char *zDir = NULL; |
| 204 | 236 |
| 205 PORT_Memcpy(result, file, len); | 237 azDirs[0] = sqlite3_temp_directory; |
| 206 result[len] = 0; | 238 azDirs[1] = getenv("TMPDIR"); |
| 207 return result; | |
| 208 } | |
| 209 | 239 |
| 210 /* | 240 for (i = 0; i < PR_ARRAY_SIZE(azDirs); i++) { |
| 211 * call back from sqlite3_exec("Pragma database_list"). Looks for the | 241 zDir = azDirs[i]; |
| 212 * temp directory, then return the file the temp directory is stored | 242 if (zDir == NULL) continue; |
| 213 * at. */ | 243 if (stat(zDir, &buf)) continue; |
| 214 static int | 244 if (!S_ISDIR(buf.st_mode)) continue; |
| 215 sdb_getTempDirCallback(void *arg, int columnCount, char **cval, char **cname) | 245 if (access(zDir, 07)) continue; |
| 216 { | 246 break; |
| 217 int i; | |
| 218 int found = 0; | |
| 219 char *file = NULL; | |
| 220 char *end, *dir; | |
| 221 char dirsep; | |
| 222 | |
| 223 /* we've already found the temp directory, don't look at any more records*/ | |
| 224 if (*(char **)arg) { | |
| 225 » return SQLITE_OK; | |
| 226 } | 247 } |
| 227 | 248 |
| 228 /* look at the columns to see if this record is the temp database, | 249 if (zDir == NULL) |
| 229 * and does it say where it is stored */ | 250 return NULL; |
| 230 for (i=0; i < columnCount; i++) { | 251 return PORT_Strdup(zDir); |
| 231 » if (PORT_Strcmp(cname[i],"name") == 0) { | 252 } |
| 232 » if (PORT_Strcmp(cval[i], "temp") == 0) { | 253 #else |
| 233 » » found++; | 254 #error "sdb_getFallbackTempDir not implemented" |
| 234 » » continue; | 255 #endif |
| 235 » } | |
| 236 » } | |
| 237 » if (PORT_Strcmp(cname[i],"file") == 0) { | |
| 238 » if (cval[i] && (*cval[i] != 0)) { | |
| 239 » » file = cval[i]; | |
| 240 » } | |
| 241 » } | |
| 242 } | |
| 243 | 256 |
| 244 /* if we couldn't find it, ask for the next record */ | 257 #ifndef SQLITE_FCNTL_TEMPFILENAME |
| 245 if (!found || !file) { | 258 /* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */ |
| 246 » return SQLITE_OK; | 259 #define SQLITE_FCNTL_TEMPFILENAME 16 |
| 247 } | 260 #endif |
| 248 | 261 |
| 249 /* drop of the database file name and just return the directory */ | |
| 250 dirsep = PR_GetDirectorySeparator(); | |
| 251 end = PORT_Strrchr(file, dirsep); | |
| 252 if (!end) { | |
| 253 return SQLITE_OK; | |
| 254 } | |
| 255 dir = sdb_strndup(file, end-file); | |
| 256 | |
| 257 *(char **)arg = dir; | |
| 258 return SQLITE_OK; | |
| 259 } | |
| 260 | |
| 261 /* | |
| 262 * find out where sqlite stores the temp tables. We do this by creating | |
| 263 * a temp table, then looking for the database name that sqlite3 creates. | |
| 264 */ | |
| 265 static char * | 262 static char * |
| 266 sdb_getTempDir(sqlite3 *sqlDB) | 263 sdb_getTempDir(sqlite3 *sqlDB) |
| 267 { | 264 { |
| 268 char *tempDir = NULL; | 265 int sqlrv; |
| 269 int sqlerr; | 266 char *result = NULL; |
| 267 char *tempName = NULL; |
| 268 char *foundSeparator = NULL; |
| 270 | 269 |
| 271 /* create a temporary table */ | 270 /* Obtain temporary filename in sqlite's directory for temporary tables */ |
| 272 sqlerr = sqlite3_exec(sqlDB, "CREATE TEMPORARY TABLE myTemp (id)", | 271 sqlrv = sqlite3_file_control(sqlDB, 0, SQLITE_FCNTL_TEMPFILENAME, |
| 273 » » » NULL, 0, NULL); | 272 » » » » (void*)&tempName); |
| 274 if (sqlerr != SQLITE_OK) { | 273 if (sqlrv == SQLITE_NOTFOUND) { |
| 274 » /* SQLITE_FCNTL_TEMPFILENAME not implemented because we are using |
| 275 » * an older SQLite. */ |
| 276 » return sdb_getFallbackTempDir(); |
| 277 } |
| 278 if (sqlrv != SQLITE_OK) { |
| 275 return NULL; | 279 return NULL; |
| 276 } | 280 } |
| 277 /* look for through the database list for the temp directory */ | |
| 278 sqlerr = sqlite3_exec(sqlDB, "PRAGMA database_list", | |
| 279 sdb_getTempDirCallback, &tempDir, NULL); | |
| 280 | 281 |
| 281 /* drop the temp table we created */ | 282 /* We'll extract the temporary directory from tempName */ |
| 282 sqlite3_exec(sqlDB, "DROP TABLE myTemp", NULL, 0, NULL); | 283 foundSeparator = PORT_Strrchr(tempName, PR_GetDirectorySeparator()); |
| 284 if (foundSeparator) { |
| 285 » /* We shorten the temp filename string to contain only |
| 286 » * the directory name (including the trailing separator). |
| 287 » * We know the byte after the foundSeparator position is |
| 288 » * safe to use, in the shortest scenario it contains the |
| 289 » * end-of-string byte. |
| 290 » * By keeping the separator at the found position, it will |
| 291 » * even work if tempDir consists of the separator, only. |
| 292 » * (In this case the toplevel directory will be used for |
| 293 » * access speed testing). */ |
| 294 » ++foundSeparator; |
| 295 » *foundSeparator = 0; |
| 283 | 296 |
| 284 if (sqlerr != SQLITE_OK) { | 297 » /* Now we copy the directory name for our caller */ |
| 285 » return NULL; | 298 » result = PORT_Strdup(tempName); |
| 286 } | 299 } |
| 287 return tempDir; | 300 |
| 301 sqlite3_free(tempName); |
| 302 return result; |
| 288 } | 303 } |
| 289 | 304 |
| 290 | |
| 291 /* | 305 /* |
| 292 * Map SQL_LITE errors to PKCS #11 errors as best we can. | 306 * Map SQL_LITE errors to PKCS #11 errors as best we can. |
| 293 */ | 307 */ |
| 294 static CK_RV | 308 static CK_RV |
| 295 sdb_mapSQLError(sdbDataType type, int sqlerr) | 309 sdb_mapSQLError(sdbDataType type, int sqlerr) |
| 296 { | 310 { |
| 297 switch (sqlerr) { | 311 switch (sqlerr) { |
| 298 /* good matches */ | 312 /* good matches */ |
| 299 case SQLITE_OK: | 313 case SQLITE_OK: |
| 300 case SQLITE_DONE: | 314 case SQLITE_DONE: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 319 } | 333 } |
| 320 return CKR_GENERAL_ERROR; | 334 return CKR_GENERAL_ERROR; |
| 321 } | 335 } |
| 322 | 336 |
| 323 | 337 |
| 324 /* | 338 /* |
| 325 * build up database name from a directory, prefix, name, version and flags. | 339 * build up database name from a directory, prefix, name, version and flags. |
| 326 */ | 340 */ |
| 327 static char *sdb_BuildFileName(const char * directory, | 341 static char *sdb_BuildFileName(const char * directory, |
| 328 const char *prefix, const char *type, | 342 const char *prefix, const char *type, |
| 329 » » » int version, int flags) | 343 » » » int version) |
| 330 { | 344 { |
| 331 char *dbname = NULL; | 345 char *dbname = NULL; |
| 332 /* build the full dbname */ | 346 /* build the full dbname */ |
| 333 dbname = sqlite3_mprintf("%s/%s%s%d.db",directory, prefix, type, version); | 347 dbname = sqlite3_mprintf("%s%c%s%s%d.db", directory, |
| 348 » » » (int)(unsigned char)PR_GetDirectorySeparator(), |
| 349 » » » prefix, type, version); |
| 334 return dbname; | 350 return dbname; |
| 335 } | 351 } |
| 336 | 352 |
| 337 | 353 |
| 338 /* | 354 /* |
| 339 * find out how expensive the access system call is for non-existant files | 355 * find out how expensive the access system call is for non-existant files |
| 340 * in the given directory. Return the number of operations done in 33 ms. | 356 * in the given directory. Return the number of operations done in 33 ms. |
| 341 */ | 357 */ |
| 342 static PRUint32 | 358 static PRUint32 |
| 343 sdb_measureAccess(const char *directory) | 359 sdb_measureAccess(const char *directory) |
| 344 { | 360 { |
| 345 PRUint32 i; | 361 PRUint32 i; |
| 346 PRIntervalTime time; | 362 PRIntervalTime time; |
| 347 PRIntervalTime delta; | 363 PRIntervalTime delta; |
| 348 PRIntervalTime duration = PR_MillisecondsToInterval(33); | 364 PRIntervalTime duration = PR_MillisecondsToInterval(33); |
| 365 const char *doesntExistName = "_dOeSnotExist_.db"; |
| 366 char *temp, *tempStartOfFilename; |
| 367 size_t maxTempLen, maxFileNameLen, directoryLength; |
| 349 | 368 |
| 350 /* no directory, just return one */ | 369 /* no directory, just return one */ |
| 351 if (directory == NULL) { | 370 if (directory == NULL) { |
| 352 return 1; | 371 return 1; |
| 353 } | 372 } |
| 354 | 373 |
| 374 /* our calculation assumes time is a 4 bytes == 32 bit integer */ |
| 375 PORT_Assert(sizeof(time) == 4); |
| 376 |
| 377 directoryLength = strlen(directory); |
| 378 |
| 379 maxTempLen = directoryLength + strlen(doesntExistName) |
| 380 + 1 /* potential additional separator char */ |
| 381 + 11 /* max chars for 32 bit int plus potential sign */ |
| 382 + 1; /* zero terminator */ |
| 383 |
| 384 temp = PORT_Alloc(maxTempLen); |
| 385 if (!temp) { |
| 386 return 1; |
| 387 } |
| 388 |
| 389 /* We'll copy directory into temp just once, then ensure it ends |
| 390 * with the directory separator, then remember the position after |
| 391 * the separator, and calculate the number of remaining bytes. */ |
| 392 |
| 393 strcpy(temp, directory); |
| 394 if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) { |
| 395 temp[directoryLength++] = PR_GetDirectorySeparator(); |
| 396 } |
| 397 tempStartOfFilename = temp + directoryLength; |
| 398 maxFileNameLen = maxTempLen - directoryLength; |
| 399 |
| 355 /* measure number of Access operations that can be done in 33 milliseconds | 400 /* measure number of Access operations that can be done in 33 milliseconds |
| 356 * (1/30'th of a second), or 10000 operations, which ever comes first. | 401 * (1/30'th of a second), or 10000 operations, which ever comes first. |
| 357 */ | 402 */ |
| 358 time = PR_IntervalNow(); | 403 time = PR_IntervalNow(); |
| 359 for (i=0; i < 10000u; i++) { | 404 for (i=0; i < 10000u; i++) { |
| 360 char *temp; | |
| 361 PRIntervalTime next; | 405 PRIntervalTime next; |
| 362 | 406 |
| 363 temp = sdb_BuildFileName(directory,"","._dOeSnotExist_", time+i, 0); | 407 » /* We'll use the variable part first in the filename string, just in |
| 408 » * case it's longer than assumed, so if anything gets cut off, it |
| 409 » * will be cut off from the constant part. |
| 410 » * This code assumes the directory name at the beginning of |
| 411 » * temp remains unchanged during our loop. */ |
| 412 PR_snprintf(tempStartOfFilename, maxFileNameLen, |
| 413 » » ".%lu%s", (PRUint32)(time+i), doesntExistName); |
| 364 PR_Access(temp,PR_ACCESS_EXISTS); | 414 PR_Access(temp,PR_ACCESS_EXISTS); |
| 365 sqlite3_free(temp); | |
| 366 next = PR_IntervalNow(); | 415 next = PR_IntervalNow(); |
| 367 delta = next - time; | 416 delta = next - time; |
| 368 if (delta >= duration) | 417 if (delta >= duration) |
| 369 break; | 418 break; |
| 370 } | 419 } |
| 371 | 420 |
| 421 PORT_Free(temp); |
| 422 |
| 372 /* always return 1 or greater */ | 423 /* always return 1 or greater */ |
| 373 return i ? i : 1u; | 424 return i ? i : 1u; |
| 374 } | 425 } |
| 375 | 426 |
| 376 /* | 427 /* |
| 377 * some file sytems are very slow to run sqlite3 on, particularly if the | 428 * some file sytems are very slow to run sqlite3 on, particularly if the |
| 378 * access count is pretty high. On these filesystems is faster to create | 429 * access count is pretty high. On these filesystems is faster to create |
| 379 * a temporary database on the local filesystem and access that. This | 430 * a temporary database on the local filesystem and access that. This |
| 380 * code uses a temporary table to create that cache. Temp tables are | 431 * code uses a temporary table to create that cache. Temp tables are |
| 381 * automatically cleared when the database handle it was created on | 432 * automatically cleared when the database handle it was created on |
| (...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 } | 1980 } |
| 1930 | 1981 |
| 1931 | 1982 |
| 1932 /* sdbopen */ | 1983 /* sdbopen */ |
| 1933 CK_RV | 1984 CK_RV |
| 1934 s_open(const char *directory, const char *certPrefix, const char *keyPrefix, | 1985 s_open(const char *directory, const char *certPrefix, const char *keyPrefix, |
| 1935 int cert_version, int key_version, int flags, | 1986 int cert_version, int key_version, int flags, |
| 1936 SDB **certdb, SDB **keydb, int *newInit) | 1987 SDB **certdb, SDB **keydb, int *newInit) |
| 1937 { | 1988 { |
| 1938 char *cert = sdb_BuildFileName(directory, certPrefix, | 1989 char *cert = sdb_BuildFileName(directory, certPrefix, |
| 1939 » » » » "cert", cert_version, flags); | 1990 » » » » "cert", cert_version); |
| 1940 char *key = sdb_BuildFileName(directory, keyPrefix, | 1991 char *key = sdb_BuildFileName(directory, keyPrefix, |
| 1941 » » » » "key", key_version, flags); | 1992 » » » » "key", key_version); |
| 1942 CK_RV error = CKR_OK; | 1993 CK_RV error = CKR_OK; |
| 1943 int inUpdate; | 1994 int inUpdate; |
| 1944 PRUint32 accessOps; | 1995 PRUint32 accessOps; |
| 1945 | 1996 |
| 1946 if (certdb) | 1997 if (certdb) |
| 1947 *certdb = NULL; | 1998 *certdb = NULL; |
| 1948 if (keydb) | 1999 if (keydb) |
| 1949 *keydb = NULL; | 2000 *keydb = NULL; |
| 1950 *newInit = 0; | 2001 *newInit = 0; |
| 1951 | 2002 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 s_shutdown() | 2070 s_shutdown() |
| 2020 { | 2071 { |
| 2021 #ifdef SQLITE_UNSAFE_THREADS | 2072 #ifdef SQLITE_UNSAFE_THREADS |
| 2022 if (sqlite_lock) { | 2073 if (sqlite_lock) { |
| 2023 PR_DestroyLock(sqlite_lock); | 2074 PR_DestroyLock(sqlite_lock); |
| 2024 sqlite_lock = NULL; | 2075 sqlite_lock = NULL; |
| 2025 } | 2076 } |
| 2026 #endif | 2077 #endif |
| 2027 return CKR_OK; | 2078 return CKR_OK; |
| 2028 } | 2079 } |
| OLD | NEW |