Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix CGI processing so that requests sent over SSH process query parameters. Add the --ssh-sim option to the test-http command (used to debug the previous). Harden the "fossil get" command so that it can checks filenames and does not write a file that is outside of the designated --dest. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | get-command |
| Files: | files | file ages | folders |
| SHA3-256: |
9a767601780a07700db90595857d5f48 |
| User & Date: | drh 2025-10-15 21:33:02.390 |
Context
|
2025-10-15
| ||
| 21:58 | Improved comments and extra abuse defense. ... (check-in: a1f420c6c6 user: drh tags: get-command) | |
| 21:33 | Fix CGI processing so that requests sent over SSH process query parameters. Add the --ssh-sim option to the test-http command (used to debug the previous). Harden the "fossil get" command so that it can checks filenames and does not write a file that is outside of the designated --dest. ... (check-in: 9a76760178 user: drh tags: get-command) | |
| 20:12 | The "ssh:"-style requests are eating the query parameters, somewhere. I don't know where yet. Don't use query parameter for the time being. ... (check-in: 8028c868d3 user: drh tags: get-command) | |
Changes
Changes to src/cgi.c.
| ︙ | ︙ | |||
2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 |
cgi_setenv("SCRIPT_NAME", "");
}
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
if( zToken[i] ) zToken[i++] = 0;
if( nCycles==0 ){
cgi_setenv("PATH_INFO", zToken);
}else{
cgi_replace_parameter("PATH_INFO", fossil_strdup(zToken));
}
/* Get all the optional fields that follow the first line.
*/
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
char *zFieldName;
char *zVal;
| > > | 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 |
cgi_setenv("SCRIPT_NAME", "");
}
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
if( zToken[i] ) zToken[i++] = 0;
if( nCycles==0 ){
cgi_setenv("PATH_INFO", zToken);
cgi_setenv("QUERY_STRING",&zToken[i]);
}else{
cgi_replace_parameter("PATH_INFO", fossil_strdup(zToken));
cgi_replace_parameter("QUERY_STRING",fossil_strdup(&zToken[i]));
}
/* Get all the optional fields that follow the first line.
*/
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
char *zFieldName;
char *zVal;
|
| ︙ | ︙ | |||
2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 |
blob_uncompress(&g.cgiIn, &g.cgiIn);
}else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
}else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
}
}
cgi_trace(0);
nCycles++;
}
/*
** This routine handles the old fossil SSH probes
*/
| > | 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 |
blob_uncompress(&g.cgiIn, &g.cgiIn);
}else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
}else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
}
}
cgi_init();
cgi_trace(0);
nCycles++;
}
/*
** This routine handles the old fossil SSH probes
*/
|
| ︙ | ︙ |
Changes to src/checkout.c.
| ︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
int bVerbose = find_option("verbose","v",0)!=0;
int bQuiet = find_option("quiet","q",0)!=0;
int bDebug = find_option("debug",0,0)!=0;
int bList = find_option("list",0,0)!=0;
const char *zSqlArchive = find_option("sqlar",0,1);
const char *z;
char *zDest = 0; /* Where to store results */
const char *zUrl; /* Url to get */
const char *zVers; /* Version name to get */
unsigned int mHttpFlags = HTTP_GENERIC|HTTP_NOCOMPRESS;
Blob in, out; /* I/O for the HTTP request */
Blob file; /* A file to extract */
sqlite3 *db; /* Database containing downloaded sqlar */
sqlite3_stmt *pStmt; /* Statement for querying the database */
| > | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
int bVerbose = find_option("verbose","v",0)!=0;
int bQuiet = find_option("quiet","q",0)!=0;
int bDebug = find_option("debug",0,0)!=0;
int bList = find_option("list",0,0)!=0;
const char *zSqlArchive = find_option("sqlar",0,1);
const char *z;
char *zDest = 0; /* Where to store results */
char *zSql; /* SQL used to query the results */
const char *zUrl; /* Url to get */
const char *zVers; /* Version name to get */
unsigned int mHttpFlags = HTTP_GENERIC|HTTP_NOCOMPRESS;
Blob in, out; /* I/O for the HTTP request */
Blob file; /* A file to extract */
sqlite3 *db; /* Database containing downloaded sqlar */
sqlite3_stmt *pStmt; /* Statement for querying the database */
|
| ︙ | ︙ | |||
539 540 541 542 543 544 545 |
fossil_fatal("\"%s\" already exists", zDest);
}
}
}
/* Construct a subpath on the URL if necessary */
if( g.url.isSsh || g.url.isFile ){
| | | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
fossil_fatal("\"%s\" already exists", zDest);
}
}
}
/* Construct a subpath on the URL if necessary */
if( g.url.isSsh || g.url.isFile ){
g.url.subpath = mprintf("/sqlar?r=%t&name=%t.sqlar", zVers, zDest);
}
if( bDebug ){
urlparse_print(0);
}
/* Fetch the ZIP archive for the requested check-in */
|
| ︙ | ︙ | |||
569 570 571 572 573 574 575 |
rc = sqlite3_deserialize(db, 0, (unsigned char*)blob_buffer(&out), sz, sz,
SQLITE_DESERIALIZE_READONLY);
}
if( rc!=SQLITE_OK ){
fossil_fatal("Cannot create an in-memory database: %s",
sqlite3_errmsg(db));
}
| < | > | > | | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 |
rc = sqlite3_deserialize(db, 0, (unsigned char*)blob_buffer(&out), sz, sz,
SQLITE_DESERIALIZE_READONLY);
}
if( rc!=SQLITE_OK ){
fossil_fatal("Cannot create an in-memory database: %s",
sqlite3_errmsg(db));
}
zSql = mprintf("SELECT name, mode, sz, data FROM sqlar"
" WHERE name GLOB '%q*'", zDest);
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
fossil_free(zSql);
if( rc!=0 ){
fossil_fatal("SQL error: %s\n", sqlite3_errmsg(db));
}
blob_init(&file, 0, 0);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zFilename = (const char*)sqlite3_column_text(pStmt, 0);
int mode = sqlite3_column_int(pStmt, 1);
int sz = sqlite3_column_int(pStmt, 2);
if( bList ){
fossil_print("%s\n", zFilename);
}else if( mode & 0x4000 ){
/* A directory name */
nDir++;
file_mkdir(zFilename, ExtFILE, 1);
}else{
/* A file */
unsigned char *inBuf = (unsigned char*)sqlite3_column_blob(pStmt,3);
unsigned int nIn = (unsigned int)sqlite3_column_bytes(pStmt,3);
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 |
** using this command interactively over SSH. A better solution would be
** to use a different command for "ssh" sync, but we cannot do that without
** breaking legacy.
**
** Options:
** --csrf-safe N Set cgi_csrf_safe() to to return N
** --nobody Pretend to be user "nobody"
** --test Do not do special "sync" processing when operating
** over an SSH link
** --th-trace Trace TH1 execution (for debugging purposes)
** --usercap CAP User capability string (Default: "sxy")
*/
void cmd_test_http(void){
const char *zIpAddr; /* IP address of remote client */
const char *zUserCap;
int bTest = 0;
const char *zCsrfSafe = find_option("csrf-safe",0,1);
Th_InitTraceLog();
if( zCsrfSafe ) g.okCsrf = atoi(zCsrfSafe);
zUserCap = find_option("usercap",0,1);
if( !find_option("nobody",0,0) ){
if( zUserCap==0 ){
g.useLocalauth = 1;
zUserCap = "sxy";
| > > > > | 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 |
** using this command interactively over SSH. A better solution would be
** to use a different command for "ssh" sync, but we cannot do that without
** breaking legacy.
**
** Options:
** --csrf-safe N Set cgi_csrf_safe() to to return N
** --nobody Pretend to be user "nobody"
** --ssh-sim Pretend to be over an SSH connection
** --test Do not do special "sync" processing when operating
** over an SSH link
** --th-trace Trace TH1 execution (for debugging purposes)
** --usercap CAP User capability string (Default: "sxy")
*/
void cmd_test_http(void){
const char *zIpAddr; /* IP address of remote client */
const char *zUserCap;
int bTest = 0;
const char *zCsrfSafe = find_option("csrf-safe",0,1);
if( find_option("ssh-sim",0,0)!=0 ){
putenv("SSH_CONNECTION=127.0.0.1 12345 127.0.0.2 23456");
}
Th_InitTraceLog();
if( zCsrfSafe ) g.okCsrf = atoi(zCsrfSafe);
zUserCap = find_option("usercap",0,1);
if( !find_option("nobody",0,0) ){
if( zUserCap==0 ){
g.useLocalauth = 1;
zUserCap = "sxy";
|
| ︙ | ︙ |