Add the --safe to the CLI. Also the --nonce option and the .nonce command.

FossilOrigin-Name: c76870cb1a8e2e1389ad864c51b9f596dff21df8bb58f438f0a2cacfa63b22a4
This commit is contained in:
drh 2021-08-26 18:31:39 +00:00
parent 5ced0a914e
commit b97e2ad10a
3 changed files with 129 additions and 9 deletions

View File

@ -1,5 +1,5 @@
C Correctly\spreserve\sthe\scollating\ssequence\sfor\sa\scolumn\swhen\schanging\nits\sdatatype.\s\sFix\sfor\sthe\sproblem\sreported\sby\n[forum:/forumpost/e5c76b738e|forum\spost\se5c76b738e].\s\sTest\scases\nin\sTH3.
D 2021-08-24T17:07:44.447
C Add\sthe\s--safe\sto\sthe\sCLI.\s\sAlso\sthe\s--nonce\soption\sand\sthe\s.nonce\scommand.
D 2021-08-26T18:31:39.329
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -545,7 +545,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c b2c48dfc02b486fd2da2be1605503615958ba1997d40d994c2946975d0150a31
F src/shell.c.in f795a4ae3c35631f5edcfa754c7824ff1d8a75b23a07e22e664b50f82e826346
F src/shell.c.in 34cc533f27d522c7c93fe38c99867c460b0b08be9c1c315dbd360ba5d865b19f
F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
@ -1922,7 +1922,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d953646a63bf96a8e6e57fefaa60ae1487e5e4eb776fb38cd9c4ce002e74d016
R d53f561ead2efd21aac670378e59272f
P c7f0813cabf9d8ab367bead5ba8cf20132b8bb9274d8e47b76ad66a10517dd2a
R 96ba0fa0400f19ae37fbb446bcbce223
U drh
Z c6e1ab5b9f0457c342ae407c84026d23
Z c0d94ba9195f86107b44ea4e3e28e613

View File

@ -1 +1 @@
c7f0813cabf9d8ab367bead5ba8cf20132b8bb9274d8e47b76ad66a10517dd2a
c76870cb1a8e2e1389ad864c51b9f596dff21df8bb58f438f0a2cacfa63b22a4

View File

@ -1104,6 +1104,8 @@ struct ShellState {
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
u8 bSafeMode; /* True to prohibit unsafe operations */
u8 bSafeModePersist; /* The long-term value of bSafeMode */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
@ -1155,8 +1157,9 @@ struct ShellState {
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
int iIndent; /* Index of current op in aiIndent[] */
char *zNonce; /* Nonce for temporary safe-mode excapes */
EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
};
@ -1292,6 +1295,27 @@ static void shellPutsFunc(
sqlite3_result_value(pCtx, apVal[0]);
}
/*
** If in safe mode, print an error message described by the arguments
** and exit immediately.
*/
static void failIfSafeMode(
ShellState *p,
const char *zErrMsg,
...
){
if( p->bSafeMode ){
va_list ap;
char *zMsg;
va_start(ap, zErrMsg);
zMsg = sqlite3_vmprintf(zErrMsg, ap);
va_end(ap);
raw_printf(stderr, "line %d: ", p->lineno);
utf8_printf(stderr, "%s\n", zMsg);
exit(1);
}
}
/*
** SQL function: edit(VALUE)
** edit(VALUE,EDITOR)
@ -1769,6 +1793,49 @@ static BOOL WINAPI ConsoleCtrlHandler(
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This authorizer runs in safe mode.
*/
static int safeModeAuth(
void *pClientData,
int op,
const char *zA1,
const char *zA2,
const char *zA3,
const char *zA4
){
ShellState *p = (ShellState*)pClientData;
static const char *azProhibitedFunctions[] = {
"edit",
"fts3_tokenizer",
"load_extension",
"readfile",
"writefile",
"zipfile",
"zipfile_cds",
};
UNUSED_PARAMETER(zA2);
UNUSED_PARAMETER(zA3);
UNUSED_PARAMETER(zA4);
switch( op ){
case SQLITE_ATTACH: {
failIfSafeMode(p, "cannot run ATTACH in safe mode");
break;
}
case SQLITE_FUNCTION: {
int i;
for(i=0; i<ArraySize(azProhibitedFunctions); i++){
if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
failIfSafeMode(p, "cannot use the %s() function in safe mode",
azProhibitedFunctions[i]);
}
}
break;
}
}
return SQLITE_OK;
}
/*
** When the ".auth ON" is set, the following authorizer callback is
** invoked. It always returns SQLITE_OK.
@ -1811,6 +1878,7 @@ static int shellAuth(
}
}
raw_printf(p->out, "\n");
if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
return SQLITE_OK;
}
#endif
@ -3984,6 +4052,7 @@ static const char *(azHelp[]) = {
" table ASCII-art table",
" tabs Tab-separated values",
" tcl TCL list elements",
".nonce STRING Disable safe mode for one command if the nonce matches",
".nullvalue STRING Use STRING in place of NULL values",
".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
" If FILE begins with '|' then open as a pipe",
@ -4698,6 +4767,9 @@ static void open_db(ShellState *p, int openFlags){
}
#endif
}
if( p->bSafeModePersist && p->db!=0 ){
sqlite3_set_authorizer(p->db, safeModeAuth, p);
}
}
/*
@ -7461,6 +7533,8 @@ static int do_meta_command(char *zLine, ShellState *p){
open_db(p, 0);
if( booleanValue(azArg[1]) ){
sqlite3_set_authorizer(p->db, shellAuth, p);
}else if( p->bSafeModePersist ){
sqlite3_set_authorizer(p->db, safeModeAuth, p);
}else{
sqlite3_set_authorizer(p->db, 0, 0);
}
@ -7470,6 +7544,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
open_db(p, 0);
failIfSafeMode(p, "cannot run .archive in safe mode");
rc = arDotCommand(p, 0, azArg, nArg);
}else
#endif
@ -7484,6 +7559,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int j;
int bAsync = 0;
const char *zVfs = 0;
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
for(j=1; j<nArg; j++){
const char *z = azArg[j];
if( z[0]=='-' ){
@ -7572,6 +7648,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='c' && strcmp(azArg[0],"cd")==0 ){
failIfSafeMode(p, "cannot run .cd in safe mode");
if( nArg==2 ){
#if defined(_WIN32) || defined(WIN32)
wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
@ -7625,6 +7702,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
failIfSafeMode(p, "cannot run .clone in safe mode");
if( nArg==2 ){
tryToClone(p, azArg[1]);
}else{
@ -8186,6 +8264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
@ -8637,6 +8716,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
const char *zFile, *zProc;
char *zErrMsg = 0;
failIfSafeMode(p, "cannot run .load in safe mode");
if( nArg<2 ){
raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
rc = 1;
@ -8655,6 +8735,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif
if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
failIfSafeMode(p, "cannot run .log in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .log FILENAME\n");
rc = 1;
@ -8725,6 +8806,19 @@ static int do_meta_command(char *zLine, ShellState *p){
p->cMode = p->mode;
}else
if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]);
exit(1);
}
p->bSafeMode = 0;
return 0; /* Return immediately to bypass the safe mode reset
** at the end of this procedure */
}else
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
if( nArg==2 ){
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
@ -8816,7 +8910,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}
/* If a filename is specified, try to open it first */
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
if( p->bSafeMode
&& p->openMode!=SHELL_OPEN_HEXDB
&& zNewFilename
&& strcmp(zNewFilename,":memory:")!=0
){
failIfSafeMode(p, "cannot open disk-based database files in safe mode");
}
p->pAuxDb->zDbFilename = zNewFilename;
open_db(p, OPEN_DB_KEEPALIVE);
if( p->db==0 ){
@ -8844,6 +8945,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int bBOM = 0;
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
if( c=='e' ){
eMode = 'x';
bOnce = 2;
@ -9116,6 +9218,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
FILE *inSaved = p->in;
int savedLineno = p->lineno;
failIfSafeMode(p, "cannot run .read in safe mode");
if( nArg!=2 ){
raw_printf(stderr, "Usage: .read FILE\n");
rc = 1;
@ -9154,6 +9257,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_backup *pBackup;
int nTimeout = 0;
failIfSafeMode(p, "cannot run .restore in safe mode");
if( nArg==2 ){
zSrcFile = azArg[1];
zDb = "main";
@ -9403,6 +9507,7 @@ static int do_meta_command(char *zLine, ShellState *p){
*/
if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
FILE *out = 0;
failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
if( nCmd!=2 ) goto session_syntax_error;
if( pSession->p==0 ) goto session_not_open;
out = fopen(azCmd[1], "wb");
@ -9817,6 +9922,7 @@ static int do_meta_command(char *zLine, ShellState *p){
){
char *zCmd;
int i, x;
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
if( nArg<2 ){
raw_printf(stderr, "Usage: .system COMMAND\n");
rc = 1;
@ -10488,6 +10594,7 @@ meta_command_exit:
p->outCount--;
if( p->outCount==0 ) output_reset(p);
}
p->bSafeMode = p->bSafeModePersist;
return rc;
}
@ -10685,6 +10792,7 @@ static int process_input(ShellState *p){
}else{
clearTempFile(p);
}
p->bSafeMode = p->bSafeModePersist;
}else if( nSql && _all_whitespace(zSql) ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
nSql = 0;
@ -10851,10 +10959,12 @@ static const char zOptions[] =
#endif
" -newline SEP set output row separator. Default: '\\n'\n"
" -nofollow refuse to open symbolic links to database files\n"
" -nonce STRING set the safe-mode escape nonce\n"
" -nullvalue TEXT set text string for NULL values. Default ''\n"
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
" -quote set output mode to 'quote'\n"
" -readonly open the database read-only\n"
" -safe enable safe-mode\n"
" -separator SEP set output column separator. Default: '|'\n"
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
" -sorterref SIZE sorter references threshold size\n"
@ -11200,6 +11310,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
sqlite3MemTraceActivate(stderr);
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
}else if( strcmp(z,"-nonce")==0 ){
free(data.zNonce);
data.zNonce = strdup(argv[++i]);
}else if( strcmp(z,"-safe")==0 ){
/* no-op - catch this on the second pass */
}
}
verify_uninitialized();
@ -11362,6 +11477,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
i+=2;
}else if( strcmp(z,"-threadsafe")==0 ){
i+=2;
}else if( strcmp(z,"-nonce")==0 ){
i += 2;
}else if( strcmp(z,"-mmap")==0 ){
i++;
}else if( strcmp(z,"-memtrace")==0 ){
@ -11420,6 +11537,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
readStdin = 0;
break;
#endif
}else if( strcmp(z,"-safe")==0 ){
data.bSafeMode = data.bSafeModePersist = 1;
}else{
utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
raw_printf(stderr,"Use -help for a list of options.\n");
@ -11522,6 +11641,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
free(argvToFree);
#endif
free(data.colWidth);
free(data.zNonce);
/* Clear the global data structure so that valgrind will detect memory
** leaks */
memset(&data, 0, sizeof(data));