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,"			\ | ||||
| 	"kvno INTEGER NOT NULL,"		\ | ||||
| 	"etype INTEGER NOT NULL,"		\ | ||||
|         "created_at INTEGER NOT NULL,"		\ | ||||
| 	"cred BLOB NOT NULL"			\ | ||||
| 	")" | ||||
|  | ||||
| @@ -113,7 +114,7 @@ typedef struct krb5_scache { | ||||
| 	"DELETE FROM principals WHERE credential_id=old.oid;"		\ | ||||
| 	"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_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_int(s->icred, 5, time(NULL)); | ||||
|  | ||||
|     ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO); | ||||
|     if (ret) return ret; | ||||
| @@ -760,7 +762,8 @@ scc_store_cred(krb5_context context, | ||||
|     return 0; | ||||
|  | ||||
| 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); | ||||
|  | ||||
|     return ret; | ||||
| @@ -814,6 +817,12 @@ scc_get_principal(krb5_context context, | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| struct cred_ctx { | ||||
|     char *drop; | ||||
|     sqlite3_stmt *stmt; | ||||
|     sqlite3_stmt *credstmt; | ||||
| }; | ||||
|  | ||||
| static krb5_error_code | ||||
| scc_get_first (krb5_context context, | ||||
| 	       krb5_ccache id, | ||||
| @@ -821,29 +830,89 @@ scc_get_first (krb5_context context, | ||||
| { | ||||
|     krb5_scache *s = SCACHE(id); | ||||
|     krb5_error_code ret; | ||||
|     sqlite3_stmt *stmt; | ||||
|     struct cred_ctx *ctx; | ||||
|     char *str, *name; | ||||
|  | ||||
|     *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); | ||||
|     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) { | ||||
| 	sqlite3_finalize(stmt); | ||||
| 	krb5_clear_error_string(context); | ||||
| 	free(ctx); | ||||
| 	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; | ||||
|     } | ||||
|     *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; | ||||
| } | ||||
| @@ -854,14 +923,15 @@ scc_get_next (krb5_context context, | ||||
| 	      krb5_cc_cursor *cursor, | ||||
| 	      krb5_creds *creds) | ||||
| { | ||||
|     sqlite3_stmt *stmt = *cursor; | ||||
|     struct cred_ctx *ctx = *cursor; | ||||
|     krb5_scache *s = SCACHE(id); | ||||
|     krb5_error_code ret; | ||||
|  | ||||
|     sqlite_uint64 oid; | ||||
|     const void *data = NULL; | ||||
|     size_t len = 0; | ||||
|  | ||||
|     ret = sqlite3_step(stmt); | ||||
| next: | ||||
|     ret = sqlite3_step(ctx->stmt); | ||||
|     if (ret == SQLITE_DONE) { | ||||
| 	krb5_clear_error_string(context); | ||||
|         return KRB5_CC_END; | ||||
| @@ -871,17 +941,31 @@ scc_get_next (krb5_context context, | ||||
|         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 " | ||||
| 			      "for SCACHE:%s:%s",  | ||||
| 			      s->name, s->file); | ||||
| 	sqlite3_reset(ctx->credstmt); | ||||
| 	return KRB5_CC_END; | ||||
|     } | ||||
|  | ||||
|     data = sqlite3_column_blob(stmt, 0); | ||||
|     len = sqlite3_column_bytes(stmt, 0); | ||||
|     data = sqlite3_column_blob(ctx->credstmt, 0); | ||||
|     len = sqlite3_column_bytes(ctx->credstmt, 0); | ||||
|  | ||||
|     ret = decode_creds(context, data, len, creds); | ||||
|     sqlite3_reset(ctx->credstmt); | ||||
|  | ||||
|     krb5_clear_error_string(context); | ||||
|     return ret; | ||||
| @@ -892,7 +976,18 @@ scc_end_get (krb5_context context, | ||||
| 	     krb5_ccache id, | ||||
| 	     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; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Love Hörnquist Åstrand
					Love Hörnquist Åstrand