Do credential iteration by temporary table.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@22829 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -104,6 +104,7 @@ typedef struct krb5_scache {
|
|||||||
"cid INTEGER NOT NULL," \
|
"cid INTEGER NOT NULL," \
|
||||||
"kvno INTEGER NOT NULL," \
|
"kvno INTEGER NOT NULL," \
|
||||||
"etype INTEGER NOT NULL," \
|
"etype INTEGER NOT NULL," \
|
||||||
|
"created_at INTEGER NOT NULL," \
|
||||||
"cred BLOB NOT NULL" \
|
"cred BLOB NOT NULL" \
|
||||||
")"
|
")"
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ typedef struct krb5_scache {
|
|||||||
"DELETE FROM principals WHERE credential_id=old.oid;" \
|
"DELETE FROM principals WHERE credential_id=old.oid;" \
|
||||||
"END"
|
"END"
|
||||||
|
|
||||||
#define SQL_ICRED "INSERT INTO credentials (cid, kvno, etype, cred) VALUES (?,?,?,?)"
|
#define SQL_ICRED "INSERT INTO credentials (cid, kvno, etype, cred, created_at) VALUES (?,?,?,?,?)"
|
||||||
#define SQL_DCRED "DELETE FROM credentials WHERE cid=?"
|
#define SQL_DCRED "DELETE FROM credentials WHERE cid=?"
|
||||||
|
|
||||||
#define SQL_CPRINCIPALS "" \
|
#define SQL_CPRINCIPALS "" \
|
||||||
@@ -706,6 +707,7 @@ scc_store_cred(krb5_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_bind_blob(s->icred, 4, data.data, data.length, free_data);
|
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);
|
ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO);
|
||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
@@ -760,7 +762,8 @@ scc_store_cred(krb5_context context,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rollback:
|
rollback:
|
||||||
krb5_set_error_string(context, "store credentials: %s", sqlite3_errmsg(s->db));
|
krb5_set_error_string(context, "store credentials: %s",
|
||||||
|
sqlite3_errmsg(s->db));
|
||||||
exec_stmt(context, s->db, "ROLLBACK", 0);
|
exec_stmt(context, s->db, "ROLLBACK", 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -814,6 +817,12 @@ scc_get_principal(krb5_context context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cred_ctx {
|
||||||
|
char *drop;
|
||||||
|
sqlite3_stmt *stmt;
|
||||||
|
sqlite3_stmt *credstmt;
|
||||||
|
};
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
scc_get_first (krb5_context context,
|
scc_get_first (krb5_context context,
|
||||||
krb5_ccache id,
|
krb5_ccache id,
|
||||||
@@ -821,29 +830,89 @@ scc_get_first (krb5_context context,
|
|||||||
{
|
{
|
||||||
krb5_scache *s = SCACHE(id);
|
krb5_scache *s = SCACHE(id);
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
sqlite3_stmt *stmt;
|
struct cred_ctx *ctx;
|
||||||
|
char *str, *name;
|
||||||
|
|
||||||
*cursor = NULL;
|
*cursor = NULL;
|
||||||
|
|
||||||
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
krb5_set_error_string(context, "malloc: out of memory");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
ret = make_database(context, s);
|
ret = make_database(context, s);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (s->cid == SCACHE_INVALID_CID)
|
|
||||||
return KRB5_CC_END;
|
|
||||||
|
|
||||||
ret = prepare_stmt(context, s->db, &stmt,
|
|
||||||
"SELECT cred FROM credentials WHERE cid = ?");
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = sqlite3_bind_int(stmt, 1, s->cid);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
sqlite3_finalize(stmt);
|
free(ctx);
|
||||||
krb5_clear_error_string(context);
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->cid == SCACHE_INVALID_CID) {
|
||||||
|
krb5_set_error_string(context, "Iterating a invalid cache %s",
|
||||||
|
s->name);
|
||||||
|
free(ctx);
|
||||||
return KRB5_CC_END;
|
return KRB5_CC_END;
|
||||||
}
|
}
|
||||||
*cursor = stmt;
|
|
||||||
|
asprintf(&name, "credIteration%luPid%d",
|
||||||
|
(unsigned long)ctx, (int)getpid());
|
||||||
|
if (name == NULL) {
|
||||||
|
krb5_set_error_string(context, "malloc: out of memory");
|
||||||
|
free(ctx);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
asprintf(&ctx->drop, "DROP TABLE %s", name);
|
||||||
|
if (ctx->drop == NULL) {
|
||||||
|
krb5_set_error_string(context, "malloc: out of memory");
|
||||||
|
free(name);
|
||||||
|
free(ctx);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
asprintf(&str, "CREATE TEMPORARY TABLE %s "
|
||||||
|
"AS SELECT oid,created_at FROM credentials WHERE cid = %lu",
|
||||||
|
name, (unsigned long)s->cid);
|
||||||
|
|
||||||
|
ret = exec_stmt(context, s->db, str, KRB5_CC_IO);
|
||||||
|
free(str);
|
||||||
|
if (ret) {
|
||||||
|
free(ctx->drop);
|
||||||
|
free(name);
|
||||||
|
free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
asprintf(&str, "SELECT oid FROM %s ORDER BY created_at", name);
|
||||||
|
if (str == NULL) {
|
||||||
|
exec_stmt(context, s->db, ctx->drop, 0);
|
||||||
|
free(ctx->drop);
|
||||||
|
free(name);
|
||||||
|
free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = prepare_stmt(context, s->db, &ctx->stmt, str);
|
||||||
|
free(str);
|
||||||
|
free(name);
|
||||||
|
if (ret) {
|
||||||
|
exec_stmt(context, s->db, ctx->drop, 0);
|
||||||
|
free(ctx->drop);
|
||||||
|
free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = prepare_stmt(context, s->db, &ctx->credstmt,
|
||||||
|
"SELECT cred FROM credentials WHERE oid = ?");
|
||||||
|
if (ret) {
|
||||||
|
sqlite3_finalize(ctx->stmt);
|
||||||
|
exec_stmt(context, s->db, ctx->drop, 0);
|
||||||
|
free(ctx->drop);
|
||||||
|
free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cursor = ctx;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -854,14 +923,15 @@ scc_get_next (krb5_context context,
|
|||||||
krb5_cc_cursor *cursor,
|
krb5_cc_cursor *cursor,
|
||||||
krb5_creds *creds)
|
krb5_creds *creds)
|
||||||
{
|
{
|
||||||
sqlite3_stmt *stmt = *cursor;
|
struct cred_ctx *ctx = *cursor;
|
||||||
krb5_scache *s = SCACHE(id);
|
krb5_scache *s = SCACHE(id);
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
sqlite_uint64 oid;
|
||||||
const void *data = NULL;
|
const void *data = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
ret = sqlite3_step(stmt);
|
next:
|
||||||
|
ret = sqlite3_step(ctx->stmt);
|
||||||
if (ret == SQLITE_DONE) {
|
if (ret == SQLITE_DONE) {
|
||||||
krb5_clear_error_string(context);
|
krb5_clear_error_string(context);
|
||||||
return KRB5_CC_END;
|
return KRB5_CC_END;
|
||||||
@@ -871,17 +941,31 @@ scc_get_next (krb5_context context,
|
|||||||
return KRB5_CC_IO;
|
return KRB5_CC_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sqlite3_column_type(stmt, 0) != SQLITE_BLOB) {
|
oid = sqlite3_column_int64(ctx->stmt, 0);
|
||||||
|
|
||||||
|
/* read cred from credentials table */
|
||||||
|
|
||||||
|
sqlite3_bind_int(ctx->credstmt, 1, oid);
|
||||||
|
|
||||||
|
ret = sqlite3_step(ctx->credstmt);
|
||||||
|
if (ret != SQLITE_ROW) {
|
||||||
|
sqlite3_reset(ctx->credstmt);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqlite3_column_type(ctx->credstmt, 0) != SQLITE_BLOB) {
|
||||||
krb5_set_error_string(context, "credential of wrong type "
|
krb5_set_error_string(context, "credential of wrong type "
|
||||||
"for SCACHE:%s:%s",
|
"for SCACHE:%s:%s",
|
||||||
s->name, s->file);
|
s->name, s->file);
|
||||||
|
sqlite3_reset(ctx->credstmt);
|
||||||
return KRB5_CC_END;
|
return KRB5_CC_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = sqlite3_column_blob(stmt, 0);
|
data = sqlite3_column_blob(ctx->credstmt, 0);
|
||||||
len = sqlite3_column_bytes(stmt, 0);
|
len = sqlite3_column_bytes(ctx->credstmt, 0);
|
||||||
|
|
||||||
ret = decode_creds(context, data, len, creds);
|
ret = decode_creds(context, data, len, creds);
|
||||||
|
sqlite3_reset(ctx->credstmt);
|
||||||
|
|
||||||
krb5_clear_error_string(context);
|
krb5_clear_error_string(context);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -892,7 +976,18 @@ scc_end_get (krb5_context context,
|
|||||||
krb5_ccache id,
|
krb5_ccache id,
|
||||||
krb5_cc_cursor *cursor)
|
krb5_cc_cursor *cursor)
|
||||||
{
|
{
|
||||||
sqlite3_finalize((sqlite3_stmt *)*cursor);
|
struct cred_ctx *ctx = *cursor;
|
||||||
|
krb5_scache *s = SCACHE(id);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sqlite3_finalize(ctx->stmt);
|
||||||
|
sqlite3_finalize(ctx->credstmt);
|
||||||
|
|
||||||
|
ret = exec_stmt(context, s->db, ctx->drop, 0);
|
||||||
|
|
||||||
|
free(ctx->drop);
|
||||||
|
free(ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user