/* * Removes a principal, including aliases and associated entry. */ static krb5_error_code hdb_sqlite_remove(krb5_context context, HDB *db, unsigned flags, krb5_const_principal principal) { krb5_error_code ret; hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); sqlite3_stmt *get_ids = hsdb->get_ids; sqlite3_stmt *rm = hsdb->remove; bind_principal(context, principal, rm, 1); ret = hdb_sqlite_exec_stmt(context, hsdb, "BEGIN IMMEDIATE TRANSACTION", HDB_ERR_UK_SERROR); if (ret != SQLITE_OK) { ret = HDB_ERR_UK_SERROR; (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); krb5_set_error_message(context, ret, "SQLite BEGIN TRANSACTION failed: %s", sqlite3_errmsg(hsdb->db)); return ret; } if ((flags & HDB_F_PRECHECK)) { ret = bind_principal(context, principal, get_ids, 1); if (ret) return ret; ret = hdb_sqlite_step(context, hsdb->db, get_ids); sqlite3_clear_bindings(get_ids); sqlite3_reset(get_ids); if (ret == SQLITE_DONE) { (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); return HDB_ERR_NOENTRY; } } ret = hdb_sqlite_step(context, hsdb->db, rm); sqlite3_clear_bindings(rm); sqlite3_reset(rm); if (ret != SQLITE_DONE) { (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); ret = HDB_ERR_UK_SERROR; krb5_set_error_message(context, ret, "sqlite remove failed: %d", ret); return ret; } if ((flags & HDB_F_PRECHECK)) { (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); return 0; } ret = hdb_sqlite_exec_stmt(context, hsdb, "COMMIT", HDB_ERR_UK_SERROR); if (ret != SQLITE_OK) krb5_warnx(context, "hdb-sqlite: COMMIT problem: %ld: %s", (long)HDB_ERR_UK_SERROR, sqlite3_errmsg(hsdb->db)); return 0; }
/** * Stores an hdb_entry in the database. If flags contains HDB_F_REPLACE * a previous entry may be replaced. * * @param context The current krb5_context * @param db Heimdal database handle * @param flags May currently only contain HDB_F_REPLACE * @param entry The data to store * * @return 0 if everything worked, an error code if not */ static krb5_error_code hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) { int ret; int i; sqlite_int64 entry_id; const HDB_Ext_Aliases *aliases; hdb_sqlite_db *hsdb = (hdb_sqlite_db *)(db->hdb_db); krb5_data value; sqlite3_stmt *get_ids = hsdb->get_ids; krb5_data_zero(&value); ret = hdb_sqlite_exec_stmt(context, hsdb, "BEGIN IMMEDIATE TRANSACTION", HDB_ERR_UK_SERROR); if(ret != SQLITE_OK) { ret = HDB_ERR_UK_SERROR; krb5_set_error_message(context, ret, "SQLite BEGIN TRANSACTION failed: %s", sqlite3_errmsg(hsdb->db)); goto rollback; } ret = hdb_seal_keys(context, db, &entry->entry); if(ret) { goto rollback; } ret = hdb_entry2value(context, &entry->entry, &value); if(ret) { goto rollback; } ret = bind_principal(context, entry->entry.principal, get_ids, 1); if (ret) goto rollback; ret = hdb_sqlite_step(context, hsdb->db, get_ids); if(ret == SQLITE_DONE) { /* No such principal */ sqlite3_bind_blob(hsdb->add_entry, 1, value.data, value.length, SQLITE_STATIC); ret = hdb_sqlite_step(context, hsdb->db, hsdb->add_entry); sqlite3_clear_bindings(hsdb->add_entry); sqlite3_reset(hsdb->add_entry); if (ret != SQLITE_DONE && ret != SQLITE_CONSTRAINT) { ret = HDB_ERR_UK_SERROR; goto rollback; } if (ret == SQLITE_CONSTRAINT) { ret = HDB_ERR_EXISTS; goto rollback; } ret = 0; ret = bind_principal(context, entry->entry.principal, hsdb->add_principal, 1); if (ret) goto rollback; ret = hdb_sqlite_step(context, hsdb->db, hsdb->add_principal); sqlite3_clear_bindings(hsdb->add_principal); sqlite3_reset(hsdb->add_principal); if (ret != SQLITE_DONE && ret != SQLITE_CONSTRAINT) { ret = HDB_ERR_UK_SERROR; goto rollback; } if (ret == SQLITE_CONSTRAINT) { ret = HDB_ERR_EXISTS; goto rollback; } /* Now let's learn what Entry ID we got for the new principal */ sqlite3_reset(get_ids); ret = hdb_sqlite_step(context, hsdb->db, get_ids); if (ret != SQLITE_ROW) { ret = HDB_ERR_UK_SERROR; goto rollback; } entry_id = sqlite3_column_int64(get_ids, 1); ret = 0; } else if(ret == SQLITE_ROW) { /* Found a principal */ if(! (flags & HDB_F_REPLACE)) /* Not allowed to replace it */ goto rollback; entry_id = sqlite3_column_int64(get_ids, 1); sqlite3_bind_int64(hsdb->delete_aliases, 1, entry_id); ret = hdb_sqlite_step_once(context, db, hsdb->delete_aliases); if (ret != SQLITE_DONE) { ret = HDB_ERR_UK_SERROR; goto rollback; } sqlite3_bind_blob(hsdb->update_entry, 1, value.data, value.length, SQLITE_STATIC); sqlite3_bind_int64(hsdb->update_entry, 2, entry_id); ret = hdb_sqlite_step_once(context, db, hsdb->update_entry); if (ret != SQLITE_DONE) { ret = HDB_ERR_UK_SERROR; goto rollback; } } else { /* Error! */ ret = HDB_ERR_UK_SERROR; goto rollback; } ret = hdb_entry_get_aliases(&entry->entry, &aliases); if(ret || aliases == NULL) goto commit; for(i = 0; i < aliases->aliases.len; i++) { ret = bind_principal(context, &aliases->aliases.val[i], hsdb->add_alias, 1); if (ret) goto rollback; sqlite3_bind_int64(hsdb->add_alias, 2, entry_id); ret = hdb_sqlite_step_once(context, db, hsdb->add_alias); if (ret == SQLITE_CONSTRAINT) { ret = HDB_ERR_EXISTS; goto rollback; } if (ret != SQLITE_DONE) { ret = HDB_ERR_UK_SERROR; goto rollback; } } commit: krb5_data_free(&value); sqlite3_clear_bindings(get_ids); sqlite3_reset(get_ids); if ((flags & HDB_F_PRECHECK)) { (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); return 0; } ret = hdb_sqlite_exec_stmt(context, hsdb, "COMMIT", HDB_ERR_UK_SERROR); if(ret != SQLITE_OK) krb5_warnx(context, "hdb-sqlite: COMMIT problem: %ld: %s", (long)HDB_ERR_UK_SERROR, sqlite3_errmsg(hsdb->db)); return ret == SQLITE_OK ? 0 : HDB_ERR_UK_SERROR; rollback: krb5_data_free(&value); sqlite3_clear_bindings(get_ids); sqlite3_reset(get_ids); krb5_warnx(context, "hdb-sqlite: store rollback problem: %d: %s", ret, sqlite3_errmsg(hsdb->db)); (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0); return ret; }
static krb5_error_code KRB5_CALLCONV scc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { sqlite_uint64 credid; krb5_scache *s = SCACHE(id); krb5_error_code ret; krb5_data data; ret = make_database(context, s); if (ret) return ret; ret = encode_creds(context, creds, &data); if (ret) return ret; sqlite3_bind_int(s->icred, 1, s->cid); { krb5_enctype etype = 0; int kvno = 0; Ticket t; size_t len; ret = decode_Ticket(creds->ticket.data, creds->ticket.length, &t, &len); if (ret == 0) { if(t.enc_part.kvno) kvno = *t.enc_part.kvno; etype = t.enc_part.etype; free_Ticket(&t); } sqlite3_bind_int(s->icred, 2, kvno); sqlite3_bind_int(s->icred, 3, etype); } sqlite3_bind_blob(s->icred, 4, data.data, data.length, free_data); sqlite3_bind_int(s->icred, 5, time(NULL)); ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO); if (ret) return ret; do { ret = sqlite3_step(s->icred); } while (ret == SQLITE_ROW); sqlite3_reset(s->icred); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add credential: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } credid = sqlite3_last_insert_rowid(s->db); { bind_principal(context, s->db, s->iprincipal, 1, creds->server); sqlite3_bind_int(s->iprincipal, 2, 1); sqlite3_bind_int(s->iprincipal, 3, credid); do { ret = sqlite3_step(s->iprincipal); } while (ret == SQLITE_ROW); sqlite3_reset(s->iprincipal); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add principal: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } } { bind_principal(context, s->db, s->iprincipal, 1, creds->client); sqlite3_bind_int(s->iprincipal, 2, 0); sqlite3_bind_int(s->iprincipal, 3, credid); do { ret = sqlite3_step(s->iprincipal); } while (ret == SQLITE_ROW); sqlite3_reset(s->iprincipal); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add principal: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } } ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO); if (ret) return ret; return 0; rollback: exec_stmt(context, s->db, "ROLLBACK", 0); return ret; }
/** * Retrieves an entry by searching for the given * principal in the Principal database table, both * for canonical principals and aliases. * * @param context The current krb5_context * @param db Heimdal database handle * @param principal The principal whose entry to search for * @param flags Currently only for HDB_F_DECRYPT * @param kvno kvno to fetch is HDB_F_KVNO_SPECIFIED use used * * @return 0 if everything worked, an error code if not */ static krb5_error_code hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) { int sqlite_error; krb5_error_code ret; hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); sqlite3_stmt *fetch = hsdb->fetch; krb5_data value; krb5_principal enterprise_principal = NULL; if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { if (principal->name.name_string.len != 1) { ret = KRB5_PARSE_MALFORMED; krb5_set_error_message(context, ret, "malformed principal: " "enterprise name with %d name components", principal->name.name_string.len); return ret; } ret = krb5_parse_name(context, principal->name.name_string.val[0], &enterprise_principal); if (ret) return ret; principal = enterprise_principal; } ret = bind_principal(context, principal, fetch, 1); if (ret) return ret; krb5_free_principal(context, enterprise_principal); sqlite_error = hdb_sqlite_step(context, hsdb->db, fetch); if (sqlite_error != SQLITE_ROW) { if(sqlite_error == SQLITE_DONE) { ret = HDB_ERR_NOENTRY; goto out; } else { ret = HDB_ERR_UK_RERROR; krb5_set_error_message(context, ret, "sqlite fetch failed: %d", sqlite_error); goto out; } } value.length = sqlite3_column_bytes(fetch, 0); value.data = (void *) sqlite3_column_blob(fetch, 0); ret = hdb_value2entry(context, &value, &entry->entry); if(ret) goto out; if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { ret = hdb_unseal_keys(context, db, &entry->entry); if(ret) { hdb_free_entry(context, entry); goto out; } } ret = 0; out: sqlite3_clear_bindings(fetch); sqlite3_reset(fetch); return ret; }
static krb5_error_code KRB5_CALLCONV scc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { krb5_scache *s = SCACHE(id); krb5_error_code ret; ret = make_database(context, s); if (ret) return ret; ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO); if (ret) return ret; if (s->cid == SCACHE_INVALID_CID) { ret = create_cache(context, s); if (ret) goto rollback; } else { sqlite3_bind_int(s->dcred, 1, s->cid); do { ret = sqlite3_step(s->dcred); } while (ret == SQLITE_ROW); sqlite3_reset(s->dcred); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to delete old " "credentials: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } } ret = bind_principal(context, s->db, s->ucachep, 1, primary_principal); if (ret) goto rollback; sqlite3_bind_int(s->ucachep, 2, s->cid); do { ret = sqlite3_step(s->ucachep); } while (ret == SQLITE_ROW); sqlite3_reset(s->ucachep); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to bind principal to cache %s", ""), sqlite3_errmsg(s->db)); goto rollback; } ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO); if (ret) return ret; return 0; rollback: exec_stmt(context, s->db, "ROLLBACK", 0); return ret; }