1 /* $NetBSD: hdb-sqlite.c,v 1.1.1.1 2011/04/13 18:14:42 elric Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Kungliga Tekniska H�gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hdb_locl.h" 37 #include "sqlite3.h" 38 39 #define MAX_RETRIES 10 40 41 typedef struct hdb_sqlite_db { 42 double version; 43 sqlite3 *db; 44 char *db_file; 45 46 sqlite3_stmt *get_version; 47 sqlite3_stmt *fetch; 48 sqlite3_stmt *get_ids; 49 sqlite3_stmt *add_entry; 50 sqlite3_stmt *add_principal; 51 sqlite3_stmt *add_alias; 52 sqlite3_stmt *delete_aliases; 53 sqlite3_stmt *update_entry; 54 sqlite3_stmt *remove; 55 sqlite3_stmt *get_all_entries; 56 57 } hdb_sqlite_db; 58 59 /* This should be used to mark updates which make the code incompatible 60 * with databases created with previous versions. Don't update it if 61 * compatibility is not broken. */ 62 #define HDBSQLITE_VERSION 0.1 63 64 #define _HDBSQLITE_STRINGIFY(x) #x 65 #define HDBSQLITE_STRINGIFY(x) _HDBSQLITE_STRINGIFY(x) 66 67 #define HDBSQLITE_CREATE_TABLES \ 68 " BEGIN TRANSACTION;" \ 69 " CREATE TABLE Version (number REAL);" \ 70 " INSERT INTO Version (number)" \ 71 " VALUES (" HDBSQLITE_STRINGIFY(HDBSQLITE_VERSION) ");" \ 72 " CREATE TABLE Principal" \ 73 " (id INTEGER PRIMARY KEY," \ 74 " principal TEXT UNIQUE NOT NULL," \ 75 " canonical INTEGER," \ 76 " entry INTEGER);" \ 77 " CREATE TABLE Entry" \ 78 " (id INTEGER PRIMARY KEY," \ 79 " data BLOB);" \ 80 " COMMIT" 81 #define HDBSQLITE_CREATE_TRIGGERS \ 82 " CREATE TRIGGER remove_principals AFTER DELETE ON Entry" \ 83 " BEGIN" \ 84 " DELETE FROM Principal" \ 85 " WHERE entry = OLD.id;" \ 86 " END" 87 #define HDBSQLITE_GET_VERSION \ 88 " SELECT number FROM Version" 89 #define HDBSQLITE_FETCH \ 90 " SELECT Entry.data FROM Principal, Entry" \ 91 " WHERE Principal.principal = ? AND" \ 92 " Entry.id = Principal.entry" 93 #define HDBSQLITE_GET_IDS \ 94 " SELECT id, entry FROM Principal" \ 95 " WHERE principal = ?" 96 #define HDBSQLITE_ADD_ENTRY \ 97 " INSERT INTO Entry (data) VALUES (?)" 98 #define HDBSQLITE_ADD_PRINCIPAL \ 99 " INSERT INTO Principal (principal, entry, canonical)" \ 100 " VALUES (?, last_insert_rowid(), 1)" 101 #define HDBSQLITE_ADD_ALIAS \ 102 " INSERT INTO Principal (principal, entry, canonical)" \ 103 " VALUES(?, ?, 0)" 104 #define HDBSQLITE_DELETE_ALIASES \ 105 " DELETE FROM Principal" \ 106 " WHERE entry = ? AND canonical = 0" 107 #define HDBSQLITE_UPDATE_ENTRY \ 108 " UPDATE Entry SET data = ?" \ 109 " WHERE id = ?" 110 #define HDBSQLITE_REMOVE \ 111 " DELETE FROM ENTRY WHERE id = " \ 112 " (SELECT entry FROM Principal" \ 113 " WHERE principal = ?)" 114 #define HDBSQLITE_GET_ALL_ENTRIES \ 115 " SELECT data FROM Entry" 116 117 /** 118 * Wrapper around sqlite3_prepare_v2. 119 * 120 * @param context The current krb5 context 121 * @param statement Where to store the pointer to the statement 122 * after preparing it 123 * @param str SQL code for the statement 124 * 125 * @return 0 if OK, an error code if not 126 */ 127 static krb5_error_code 128 hdb_sqlite_prepare_stmt(krb5_context context, 129 sqlite3 *db, 130 sqlite3_stmt **statement, 131 const char *str) 132 { 133 int ret, tries = 0; 134 135 ret = sqlite3_prepare_v2(db, str, -1, statement, NULL); 136 while((tries++ < MAX_RETRIES) && 137 ((ret == SQLITE_BUSY) || 138 (ret == SQLITE_IOERR_BLOCKED) || 139 (ret == SQLITE_LOCKED))) { 140 krb5_warnx(context, "hdb-sqlite: prepare busy"); 141 sleep(1); 142 ret = sqlite3_prepare_v2(db, str, -1, statement, NULL); 143 } 144 145 if (ret != SQLITE_OK) { 146 krb5_set_error_message(context, EINVAL, 147 "Failed to prepare stmt %s: %s", 148 str, sqlite3_errmsg(db)); 149 return EINVAL; 150 } 151 152 return 0; 153 } 154 155 /** 156 * A wrapper around sqlite3_exec. 157 * 158 * @param context The current krb5 context 159 * @param database An open sqlite3 database handle 160 * @param statement SQL code to execute 161 * @param error_code What to return if the statement fails 162 * 163 * @return 0 if OK, else error_code 164 */ 165 static krb5_error_code 166 hdb_sqlite_exec_stmt(krb5_context context, 167 sqlite3 *database, 168 const char *statement, 169 krb5_error_code error_code) 170 { 171 int ret; 172 173 ret = sqlite3_exec(database, statement, NULL, NULL, NULL); 174 175 while(((ret == SQLITE_BUSY) || 176 (ret == SQLITE_IOERR_BLOCKED) || 177 (ret == SQLITE_LOCKED))) { 178 krb5_warnx(context, "hdb-sqlite: exec busy: %d", (int)getpid()); 179 sleep(1); 180 ret = sqlite3_exec(database, statement, NULL, NULL, NULL); 181 } 182 183 if (ret != SQLITE_OK && error_code) { 184 krb5_set_error_message(context, error_code, 185 "Execute %s: %s", statement, 186 sqlite3_errmsg(database)); 187 return error_code; 188 } 189 190 return 0; 191 } 192 193 /** 194 * Opens an sqlite3 database handle to a file, may create the 195 * database file depending on flags. 196 * 197 * @param context The current krb5 context 198 * @param db Heimdal database handle 199 * @param flags Controls whether or not the file may be created, 200 * may be 0 or SQLITE_OPEN_CREATE 201 */ 202 static krb5_error_code 203 hdb_sqlite_open_database(krb5_context context, HDB *db, int flags) 204 { 205 int ret; 206 hdb_sqlite_db *hsdb = (hdb_sqlite_db*) db->hdb_db; 207 208 ret = sqlite3_open_v2(hsdb->db_file, &hsdb->db, 209 SQLITE_OPEN_READWRITE | flags, NULL); 210 211 if (ret) { 212 if (hsdb->db) { 213 ret = ENOENT; 214 krb5_set_error_message(context, ret, 215 "Error opening sqlite database %s: %s", 216 hsdb->db_file, sqlite3_errmsg(hsdb->db)); 217 sqlite3_close(hsdb->db); 218 hsdb->db = NULL; 219 } else 220 ret = krb5_enomem(context); 221 return ret; 222 } 223 224 return 0; 225 } 226 227 static int 228 hdb_sqlite_step(krb5_context context, sqlite3 *db, sqlite3_stmt *stmt) 229 { 230 int ret; 231 232 ret = sqlite3_step(stmt); 233 while(((ret == SQLITE_BUSY) || 234 (ret == SQLITE_IOERR_BLOCKED) || 235 (ret == SQLITE_LOCKED))) { 236 krb5_warnx(context, "hdb-sqlite: step busy: %d", (int)getpid()); 237 sleep(1); 238 ret = sqlite3_step(stmt); 239 } 240 return ret; 241 } 242 243 /** 244 * Closes the database and frees memory allocated for statements. 245 * 246 * @param context The current krb5 context 247 * @param db Heimdal database handle 248 */ 249 static krb5_error_code 250 hdb_sqlite_close_database(krb5_context context, HDB *db) 251 { 252 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 253 254 sqlite3_finalize(hsdb->get_version); 255 sqlite3_finalize(hsdb->fetch); 256 sqlite3_finalize(hsdb->get_ids); 257 sqlite3_finalize(hsdb->add_entry); 258 sqlite3_finalize(hsdb->add_principal); 259 sqlite3_finalize(hsdb->add_alias); 260 sqlite3_finalize(hsdb->delete_aliases); 261 sqlite3_finalize(hsdb->update_entry); 262 sqlite3_finalize(hsdb->remove); 263 sqlite3_finalize(hsdb->get_all_entries); 264 265 sqlite3_close(hsdb->db); 266 267 return 0; 268 } 269 270 /** 271 * Opens an sqlite database file and prepares it for use. 272 * If the file does not exist it will be created. 273 * 274 * @param context The current krb5_context 275 * @param db The heimdal database handle 276 * @param filename Where to store the database file 277 * 278 * @return 0 if everything worked, an error code if not 279 */ 280 static krb5_error_code 281 hdb_sqlite_make_database(krb5_context context, HDB *db, const char *filename) 282 { 283 int ret; 284 int created_file = 0; 285 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 286 287 hsdb->db_file = strdup(filename); 288 if(hsdb->db_file == NULL) 289 return ENOMEM; 290 291 ret = hdb_sqlite_open_database(context, db, 0); 292 if (ret) { 293 ret = hdb_sqlite_open_database(context, db, SQLITE_OPEN_CREATE); 294 if (ret) goto out; 295 296 created_file = 1; 297 298 ret = hdb_sqlite_exec_stmt(context, hsdb->db, 299 HDBSQLITE_CREATE_TABLES, 300 EINVAL); 301 if (ret) goto out; 302 303 ret = hdb_sqlite_exec_stmt(context, hsdb->db, 304 HDBSQLITE_CREATE_TRIGGERS, 305 EINVAL); 306 if (ret) goto out; 307 } 308 309 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 310 &hsdb->get_version, 311 HDBSQLITE_GET_VERSION); 312 if (ret) goto out; 313 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 314 &hsdb->fetch, 315 HDBSQLITE_FETCH); 316 if (ret) goto out; 317 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 318 &hsdb->get_ids, 319 HDBSQLITE_GET_IDS); 320 if (ret) goto out; 321 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 322 &hsdb->add_entry, 323 HDBSQLITE_ADD_ENTRY); 324 if (ret) goto out; 325 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 326 &hsdb->add_principal, 327 HDBSQLITE_ADD_PRINCIPAL); 328 if (ret) goto out; 329 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 330 &hsdb->add_alias, 331 HDBSQLITE_ADD_ALIAS); 332 if (ret) goto out; 333 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 334 &hsdb->delete_aliases, 335 HDBSQLITE_DELETE_ALIASES); 336 if (ret) goto out; 337 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 338 &hsdb->update_entry, 339 HDBSQLITE_UPDATE_ENTRY); 340 if (ret) goto out; 341 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 342 &hsdb->remove, 343 HDBSQLITE_REMOVE); 344 if (ret) goto out; 345 ret = hdb_sqlite_prepare_stmt(context, hsdb->db, 346 &hsdb->get_all_entries, 347 HDBSQLITE_GET_ALL_ENTRIES); 348 if (ret) goto out; 349 350 ret = hdb_sqlite_step(context, hsdb->db, hsdb->get_version); 351 if(ret == SQLITE_ROW) { 352 hsdb->version = sqlite3_column_double(hsdb->get_version, 0); 353 } 354 sqlite3_reset(hsdb->get_version); 355 ret = 0; 356 357 if(hsdb->version != HDBSQLITE_VERSION) { 358 ret = EINVAL; 359 krb5_set_error_message(context, ret, "HDBSQLITE_VERSION mismatch"); 360 } 361 362 if(ret) goto out; 363 364 return 0; 365 366 out: 367 if (hsdb->db) 368 sqlite3_close(hsdb->db); 369 if (created_file) 370 unlink(hsdb->db_file); 371 372 return ret; 373 } 374 375 /** 376 * Retrieves an entry by searching for the given 377 * principal in the Principal database table, both 378 * for canonical principals and aliases. 379 * 380 * @param context The current krb5_context 381 * @param db Heimdal database handle 382 * @param principal The principal whose entry to search for 383 * @param flags Currently only for HDB_F_DECRYPT 384 * @param kvno kvno to fetch is HDB_F_KVNO_SPECIFIED use used 385 * 386 * @return 0 if everything worked, an error code if not 387 */ 388 static krb5_error_code 389 hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 390 unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 391 { 392 int sqlite_error; 393 krb5_error_code ret; 394 char *principal_string; 395 hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); 396 sqlite3_stmt *fetch = hsdb->fetch; 397 krb5_data value; 398 399 ret = krb5_unparse_name(context, principal, &principal_string); 400 if (ret) { 401 free(principal_string); 402 return ret; 403 } 404 405 sqlite3_bind_text(fetch, 1, principal_string, -1, SQLITE_STATIC); 406 407 sqlite_error = hdb_sqlite_step(context, hsdb->db, fetch); 408 if (sqlite_error != SQLITE_ROW) { 409 if(sqlite_error == SQLITE_DONE) { 410 ret = HDB_ERR_NOENTRY; 411 goto out; 412 } else { 413 ret = EINVAL; 414 krb5_set_error_message(context, ret, 415 "sqlite fetch failed: %d", 416 sqlite_error); 417 goto out; 418 } 419 } 420 421 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 422 ret = hdb_unseal_keys(context, db, &entry->entry); 423 if(ret) { 424 hdb_free_entry(context, entry); 425 goto out; 426 } 427 } 428 429 value.length = sqlite3_column_bytes(fetch, 0); 430 value.data = (void *) sqlite3_column_blob(fetch, 0); 431 432 ret = hdb_value2entry(context, &value, &entry->entry); 433 if(ret) 434 goto out; 435 436 ret = 0; 437 438 out: 439 440 sqlite3_clear_bindings(fetch); 441 sqlite3_reset(fetch); 442 443 free(principal_string); 444 445 return ret; 446 } 447 448 /** 449 * Convenience function to step a prepared statement with no 450 * value once. 451 * 452 * @param context The current krb5_context 453 * @param statement A prepared sqlite3 statement 454 * 455 * @return 0 if everything worked, an error code if not 456 */ 457 static krb5_error_code 458 hdb_sqlite_step_once(krb5_context context, HDB *db, sqlite3_stmt *statement) 459 { 460 int ret; 461 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 462 463 ret = hdb_sqlite_step(context, hsdb->db, statement); 464 sqlite3_clear_bindings(statement); 465 sqlite3_reset(statement); 466 467 return ret; 468 } 469 470 471 /** 472 * Stores an hdb_entry in the database. If flags contains HDB_F_REPLACE 473 * a previous entry may be replaced. 474 * 475 * @param context The current krb5_context 476 * @param db Heimdal database handle 477 * @param flags May currently only contain HDB_F_REPLACE 478 * @param entry The data to store 479 * 480 * @return 0 if everything worked, an error code if not 481 */ 482 static krb5_error_code 483 hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, 484 hdb_entry_ex *entry) 485 { 486 int ret; 487 int i; 488 sqlite_int64 entry_id; 489 char *principal_string = NULL; 490 char *alias_string; 491 const HDB_Ext_Aliases *aliases; 492 493 hdb_sqlite_db *hsdb = (hdb_sqlite_db *)(db->hdb_db); 494 krb5_data value; 495 sqlite3_stmt *get_ids = hsdb->get_ids; 496 497 ret = hdb_sqlite_exec_stmt(context, hsdb->db, 498 "BEGIN IMMEDIATE TRANSACTION", EINVAL); 499 if(ret != SQLITE_OK) { 500 ret = EINVAL; 501 krb5_set_error_message(context, ret, 502 "SQLite BEGIN TRANSACTION failed: %s", 503 sqlite3_errmsg(hsdb->db)); 504 goto rollback; 505 } 506 507 ret = krb5_unparse_name(context, 508 entry->entry.principal, &principal_string); 509 if (ret) { 510 goto rollback; 511 } 512 513 ret = hdb_seal_keys(context, db, &entry->entry); 514 if(ret) { 515 goto rollback; 516 } 517 518 ret = hdb_entry2value(context, &entry->entry, &value); 519 if(ret) { 520 goto rollback; 521 } 522 523 sqlite3_bind_text(get_ids, 1, principal_string, -1, SQLITE_STATIC); 524 ret = hdb_sqlite_step(context, hsdb->db, get_ids); 525 526 if(ret == SQLITE_DONE) { /* No such principal */ 527 528 sqlite3_bind_blob(hsdb->add_entry, 1, 529 value.data, value.length, SQLITE_STATIC); 530 ret = hdb_sqlite_step(context, hsdb->db, hsdb->add_entry); 531 sqlite3_clear_bindings(hsdb->add_entry); 532 sqlite3_reset(hsdb->add_entry); 533 if(ret != SQLITE_DONE) 534 goto rollback; 535 536 sqlite3_bind_text(hsdb->add_principal, 1, 537 principal_string, -1, SQLITE_STATIC); 538 ret = hdb_sqlite_step(context, hsdb->db, hsdb->add_principal); 539 sqlite3_clear_bindings(hsdb->add_principal); 540 sqlite3_reset(hsdb->add_principal); 541 if(ret != SQLITE_DONE) 542 goto rollback; 543 544 entry_id = sqlite3_column_int64(get_ids, 1); 545 546 } else if(ret == SQLITE_ROW) { /* Found a principal */ 547 548 if(! (flags & HDB_F_REPLACE)) /* Not allowed to replace it */ 549 goto rollback; 550 551 entry_id = sqlite3_column_int64(get_ids, 1); 552 553 sqlite3_bind_int64(hsdb->delete_aliases, 1, entry_id); 554 ret = hdb_sqlite_step_once(context, db, hsdb->delete_aliases); 555 if(ret != SQLITE_DONE) 556 goto rollback; 557 558 sqlite3_bind_blob(hsdb->update_entry, 1, 559 value.data, value.length, SQLITE_STATIC); 560 sqlite3_bind_int64(hsdb->update_entry, 2, entry_id); 561 ret = hdb_sqlite_step_once(context, db, hsdb->update_entry); 562 if(ret != SQLITE_DONE) 563 goto rollback; 564 565 } else { 566 /* Error! */ 567 goto rollback; 568 } 569 570 ret = hdb_entry_get_aliases(&entry->entry, &aliases); 571 if(ret || aliases == NULL) 572 goto commit; 573 574 for(i = 0; i < aliases->aliases.len; i++) { 575 576 ret = krb5_unparse_name(context, &aliases->aliases.val[i], 577 &alias_string); 578 if (ret) { 579 free(alias_string); 580 goto rollback; 581 } 582 583 sqlite3_bind_text(hsdb->add_alias, 1, alias_string, 584 -1, SQLITE_STATIC); 585 sqlite3_bind_int64(hsdb->add_alias, 2, entry_id); 586 ret = hdb_sqlite_step_once(context, db, hsdb->add_alias); 587 588 free(alias_string); 589 590 if(ret != SQLITE_DONE) 591 goto rollback; 592 } 593 594 ret = 0; 595 596 commit: 597 598 free(principal_string); 599 600 krb5_data_free(&value); 601 602 sqlite3_clear_bindings(get_ids); 603 sqlite3_reset(get_ids); 604 605 ret = hdb_sqlite_exec_stmt(context, hsdb->db, "COMMIT", EINVAL); 606 if(ret != SQLITE_OK) 607 krb5_warnx(context, "hdb-sqlite: COMMIT problem: %d: %s", 608 ret, sqlite3_errmsg(hsdb->db)); 609 610 return ret; 611 612 rollback: 613 614 krb5_warnx(context, "hdb-sqlite: store rollback problem: %d: %s", 615 ret, sqlite3_errmsg(hsdb->db)); 616 617 free(principal_string); 618 619 ret = hdb_sqlite_exec_stmt(context, hsdb->db, 620 "ROLLBACK", EINVAL); 621 return ret; 622 } 623 624 /** 625 * This may be called often by other code, since the BDB backends 626 * can not have several open connections. SQLite can handle 627 * many processes with open handles to the database file 628 * and closing/opening the handle is an expensive operation. 629 * Hence, this function does nothing. 630 * 631 * @param context The current krb5 context 632 * @param db Heimdal database handle 633 * 634 * @return Always returns 0 635 */ 636 static krb5_error_code 637 hdb_sqlite_close(krb5_context context, HDB *db) 638 { 639 return 0; 640 } 641 642 /** 643 * The opposite of hdb_sqlite_close. Since SQLite accepts 644 * many open handles to the database file the handle does not 645 * need to be closed, or reopened. 646 * 647 * @param context The current krb5 context 648 * @param db Heimdal database handle 649 * @param flags 650 * @param mode_t 651 * 652 * @return Always returns 0 653 */ 654 static krb5_error_code 655 hdb_sqlite_open(krb5_context context, HDB *db, int flags, mode_t mode) 656 { 657 return 0; 658 } 659 660 /** 661 * Closes the databse and frees all resources. 662 * 663 * @param context The current krb5 context 664 * @param db Heimdal database handle 665 * 666 * @return 0 on success, an error code if not 667 */ 668 static krb5_error_code 669 hdb_sqlite_destroy(krb5_context context, HDB *db) 670 { 671 int ret; 672 hdb_sqlite_db *hsdb; 673 674 ret = hdb_clear_master_key(context, db); 675 676 hdb_sqlite_close_database(context, db); 677 678 hsdb = (hdb_sqlite_db*)(db->hdb_db); 679 680 free(hsdb->db_file); 681 free(db->hdb_db); 682 free(db); 683 684 return ret; 685 } 686 687 /* 688 * Not sure if this is needed. 689 */ 690 static krb5_error_code 691 hdb_sqlite_lock(krb5_context context, HDB *db, int operation) 692 { 693 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 694 "lock not implemented"); 695 return HDB_ERR_CANT_LOCK_DB; 696 } 697 698 /* 699 * Not sure if this is needed. 700 */ 701 static krb5_error_code 702 hdb_sqlite_unlock(krb5_context context, HDB *db) 703 { 704 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 705 "unlock not implemented"); 706 return HDB_ERR_CANT_LOCK_DB; 707 } 708 709 /* 710 * Should get the next entry, to allow iteration over all entries. 711 */ 712 static krb5_error_code 713 hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags, 714 hdb_entry_ex *entry) 715 { 716 krb5_error_code ret = 0; 717 int sqlite_error; 718 krb5_data value; 719 720 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 721 722 sqlite_error = hdb_sqlite_step(context, hsdb->db, hsdb->get_all_entries); 723 if(sqlite_error == SQLITE_ROW) { 724 /* Found an entry */ 725 value.length = sqlite3_column_bytes(hsdb->get_all_entries, 0); 726 value.data = (void *) sqlite3_column_blob(hsdb->get_all_entries, 0); 727 memset(entry, 0, sizeof(*entry)); 728 ret = hdb_value2entry(context, &value, &entry->entry); 729 } 730 else if(sqlite_error == SQLITE_DONE) { 731 /* No more entries */ 732 ret = HDB_ERR_NOENTRY; 733 sqlite3_reset(hsdb->get_all_entries); 734 } 735 else { 736 /* XXX SQLite error. Should be handled in some way. */ 737 ret = EINVAL; 738 } 739 740 return ret; 741 } 742 743 /* 744 * Should get the first entry in the database. 745 * What is flags used for? 746 */ 747 static krb5_error_code 748 hdb_sqlite_firstkey(krb5_context context, HDB *db, unsigned flags, 749 hdb_entry_ex *entry) 750 { 751 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 752 krb5_error_code ret; 753 754 sqlite3_reset(hsdb->get_all_entries); 755 756 ret = hdb_sqlite_nextkey(context, db, flags, entry); 757 if(ret) 758 return ret; 759 760 return 0; 761 } 762 763 /* 764 * Renames the database file. 765 */ 766 static krb5_error_code 767 hdb_sqlite_rename(krb5_context context, HDB *db, const char *new_name) 768 { 769 hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db; 770 int ret; 771 772 krb5_warnx(context, "hdb_sqlite_rename"); 773 774 if (strncasecmp(new_name, "sqlite:", 7) == 0) 775 new_name += 7; 776 777 hdb_sqlite_close_database(context, db); 778 779 ret = rename(hsdb->db_file, new_name); 780 free(hsdb->db_file); 781 782 hdb_sqlite_make_database(context, db, new_name); 783 784 return ret; 785 } 786 787 /* 788 * Removes a principal, including aliases and associated entry. 789 */ 790 static krb5_error_code 791 hdb_sqlite_remove(krb5_context context, HDB *db, 792 krb5_const_principal principal) 793 { 794 krb5_error_code ret; 795 char *principal_string; 796 hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); 797 sqlite3_stmt *remove = hsdb->remove; 798 799 ret = krb5_unparse_name(context, principal, &principal_string); 800 if (ret) { 801 free(principal_string); 802 return ret; 803 } 804 805 sqlite3_bind_text(remove, 1, principal_string, -1, SQLITE_STATIC); 806 807 ret = hdb_sqlite_step(context, hsdb->db, remove); 808 if (ret != SQLITE_DONE) { 809 ret = EINVAL; 810 krb5_set_error_message(context, ret, 811 "sqlite remove failed: %d", 812 ret); 813 } else 814 ret = 0; 815 816 sqlite3_clear_bindings(remove); 817 sqlite3_reset(remove); 818 819 return ret; 820 } 821 822 /** 823 * Create SQLITE object, and creates the on disk database if its doesn't exists. 824 * 825 * @param context A Kerberos 5 context. 826 * @param db a returned database handle. 827 * @param argument filename 828 * 829 * @return 0 on success, an error code if not 830 */ 831 832 krb5_error_code 833 hdb_sqlite_create(krb5_context context, HDB **db, const char *argument) 834 { 835 krb5_error_code ret; 836 hdb_sqlite_db *hsdb; 837 838 *db = calloc(1, sizeof (**db)); 839 if (*db == NULL) 840 return krb5_enomem(context); 841 842 hsdb = (hdb_sqlite_db*) calloc(1, sizeof (*hsdb)); 843 if (hsdb == NULL) { 844 free(*db); 845 *db = NULL; 846 return krb5_enomem(context); 847 } 848 849 (*db)->hdb_db = hsdb; 850 851 /* XXX make_database should make sure everything else is freed on error */ 852 ret = hdb_sqlite_make_database(context, *db, argument); 853 if (ret) { 854 free((*db)->hdb_db); 855 free(*db); 856 857 return ret; 858 } 859 860 (*db)->hdb_master_key_set = 0; 861 (*db)->hdb_openp = 0; 862 (*db)->hdb_capability_flags = 0; 863 864 (*db)->hdb_open = hdb_sqlite_open; 865 (*db)->hdb_close = hdb_sqlite_close; 866 867 (*db)->hdb_lock = hdb_sqlite_lock; 868 (*db)->hdb_unlock = hdb_sqlite_unlock; 869 (*db)->hdb_firstkey = hdb_sqlite_firstkey; 870 (*db)->hdb_nextkey = hdb_sqlite_nextkey; 871 (*db)->hdb_fetch_kvno = hdb_sqlite_fetch_kvno; 872 (*db)->hdb_store = hdb_sqlite_store; 873 (*db)->hdb_remove = hdb_sqlite_remove; 874 (*db)->hdb_destroy = hdb_sqlite_destroy; 875 (*db)->hdb_rename = hdb_sqlite_rename; 876 (*db)->hdb__get = NULL; 877 (*db)->hdb__put = NULL; 878 (*db)->hdb__del = NULL; 879 880 return 0; 881 } 882