From 0df3c5869a854d0d0d94f68010905196ed6d8067 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 21 Feb 2025 12:53:54 +1030 Subject: [PATCH] plugins/sql: allow deprecated field access if wildcards are used. Otherwise, deprecating a field causes SELECT * to fail: ``` > l1.rpc.sql(f"SELECT * FROM peerchannels;") ... > raise RpcError(method, payload, resp['error']) E pyln.client.lightning.RpcError: RPC call failed: method: sql, payload: ('SELECT * FROM peerchannels;',), error: {'code': -1, 'message': 'query failed with access to peerchannels.max_total_htlc_in_msat is prohibited (Deprecated column table peerchannels.max_total_htlc_in_msat)'} ``` So if they use a wildcard, allow access: though "SELECT *" is fraught, "COUNT(*)" is perfectly legit. Signed-off-by: Rusty Russell --- plugins/sql.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/sql.c b/plugins/sql.c index c6ec13f4b..cba474cb7 100644 --- a/plugins/sql.c +++ b/plugins/sql.c @@ -93,6 +93,7 @@ struct db_query { sqlite3_stmt *stmt; struct table_desc **tables; const char *authfail; + bool has_wildcard; }; struct table_desc { @@ -292,11 +293,14 @@ static int sqlite_authorize(void *dbq_, int code, if (!col->depr_start) return SQLITE_OK; - /* Can this command see this? */ + /* Can this command see this? We have to allow this + * (as null) with "SELECT *" though! */ if (!command_deprecated_in_named_ok(dbq->cmd, td->cmdname, col->jsonname, col->depr_start, col->depr_end)) { + if (dbq->has_wildcard) + return SQLITE_IGNORE; dbq->authfail = tal_fmt(dbq, "Deprecated column table %s.%s", a, b); return SQLITE_DENY; } @@ -1051,6 +1055,10 @@ static struct command_result *json_sql(struct command *cmd, dbq->tables = tal_arr(dbq, struct table_desc *, 0); dbq->authfail = NULL; dbq->cmd = cmd; + /* We might want to warn on SELECT *, since that is not really + * recommended as fields change, but SELECT COUNT(*) is totally + * legitimate. So we suppress deprecation errors in this case */ + dbq->has_wildcard = (strchr(query, '*') != NULL); /* This both checks we're not altering, *and* tells us what * tables to refresh. */