Fossil SCM

Show the table of public phantoms directly on the security audit page. Dig deeper looking for the source of public phantoms.

drh 2020-04-14 14:27 trunk
Commit 941280ae0aa53d1da49de9d20b6f6b3771039c7a6bf355ca97323c8c262a1aaa
2 files changed +105 -53 +4 -7
+105 -53
--- src/name.c
+++ src/name.c
@@ -968,10 +968,75 @@
968968
@ summary TEXT, -- Summary comment for the object
969969
@ ref TEXT -- hash of an object to link against
970970
@ );
971971
@ CREATE INDEX desctype ON description(summary) WHERE summary='unknown';
972972
;
973
+
974
+/*
975
+** Attempt to describe all phantom artifacts. The artifacts are
976
+** already loaded into the description table and have summary='unknown'.
977
+** This routine attempts to generate a better summary, and possibly
978
+** fill in the ref field.
979
+*/
980
+static void describe_unknown_artifacts(){
981
+ /* Try to figure out the origin of unknown artifacts */
982
+ db_multi_exec(
983
+ "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
984
+ " SELECT description.rid, description.uuid, isPrivate, type,\n"
985
+ " CASE WHEN plink.isprim THEN '' ELSE 'merge ' END ||\n"
986
+ " 'parent of check-in', blob.uuid\n"
987
+ " FROM description, plink, blob\n"
988
+ " WHERE description.summary='unknown'\n"
989
+ " AND plink.pid=description.rid\n"
990
+ " AND blob.rid=plink.cid;"
991
+ );
992
+ db_multi_exec(
993
+ "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
994
+ " SELECT description.rid, description.uuid, isPrivate, type,\n"
995
+ " 'child of check-in', blob.uuid\n"
996
+ " FROM description, plink, blob\n"
997
+ " WHERE description.summary='unknown'\n"
998
+ " AND plink.cid=description.rid\n"
999
+ " AND blob.rid=plink.pid;"
1000
+ );
1001
+ db_multi_exec(
1002
+ "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1003
+ " SELECT description.rid, description.uuid, isPrivate, type,\n"
1004
+ " 'check-in referenced by \"'||tag.tagname ||'\" tag',\n"
1005
+ " blob.uuid\n"
1006
+ " FROM description, tagxref, tag, blob\n"
1007
+ " WHERE description.summary='unknown'\n"
1008
+ " AND tagxref.origid=description.rid\n"
1009
+ " AND tag.tagid=tagxref.tagid\n"
1010
+ " AND blob.rid=tagxref.srcid;"
1011
+ );
1012
+ db_multi_exec(
1013
+ "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1014
+ " SELECT description.rid, description.uuid, isPrivate, type,\n"
1015
+ " 'file \"'||filename.name||'\"',\n"
1016
+ " blob.uuid\n"
1017
+ " FROM description, mlink, filename, blob\n"
1018
+ " WHERE description.summary='unknown'\n"
1019
+ " AND mlink.fid=description.rid\n"
1020
+ " AND blob.rid=mlink.mid\n"
1021
+ " AND filename.fnid=mlink.fnid;"
1022
+ );
1023
+ if( !db_exists("SELECT 1 FROM description WHERE summary='unknown'") ){
1024
+ return;
1025
+ }
1026
+ add_content_sql_commands(g.db);
1027
+ db_multi_exec(
1028
+ "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1029
+ " SELECT description.rid, description.uuid, isPrivate, type,\n"
1030
+ " 'referenced by cluster', blob.uuid\n"
1031
+ " FROM description, tagxref, blob\n"
1032
+ " WHERE description.summary='unknown'\n"
1033
+ " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
1034
+ " AND blob.rid=tagxref.rid\n"
1035
+ " AND content(blob.uuid) GLOB ('*M '||blob.uuid||'*');"
1036
+ );
1037
+}
9731038
9741039
/*
9751040
** Create the description table if it does not already exists.
9761041
** Populate fields of this table with descriptions for all artifacts
9771042
** whose RID matches the SQL expression in zWhere.
@@ -1120,32 +1185,13 @@
11201185
/* Mark private elements */
11211186
db_multi_exec(
11221187
"UPDATE description SET isPrivate=1 WHERE rid IN private"
11231188
);
11241189
1125
- /* Try to figure out the origin of unknown artifacts */
1126
- db_multi_exec(
1127
- "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1128
- " SELECT description.rid, description.uuid, isPrivate, type,\n"
1129
- " CASE WHEN plink.isprim THEN '' ELSE 'merge ' END ||\n"
1130
- " 'parent of check-in', blob.uuid\n"
1131
- " FROM description, plink, blob\n"
1132
- " WHERE description.summary='unknown'\n"
1133
- " AND plink.pid=description.rid\n"
1134
- " AND blob.rid=plink.cid;"
1135
- );
1136
- db_multi_exec(
1137
- "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1138
- " SELECT description.rid, description.uuid, isPrivate, type,\n"
1139
- " 'check-in referenced by \"'||tag.tagname ||'\" tag',\n"
1140
- " blob.uuid\n"
1141
- " FROM description, tagxref, tag, blob\n"
1142
- " WHERE description.summary='unknown'\n"
1143
- " AND tagxref.origid=description.rid\n"
1144
- " AND tag.tagid=tagxref.tagid\n"
1145
- " AND blob.rid=tagxref.srcid;"
1146
- );
1190
+ if( db_exists("SELECT 1 FROM description WHERE summary='unknown'") ){
1191
+ describe_unknown_artifacts();
1192
+ }
11471193
}
11481194
11491195
/*
11501196
** Print the content of the description table on stdout.
11511197
**
@@ -1332,44 +1378,15 @@
13321378
db_finalize(&q);
13331379
style_footer();
13341380
}
13351381
13361382
/*
1337
-** WEBPAGE: phantoms
1338
-**
1339
-** Show a list of all "phantom" artifacts that are not marked as "private".
1340
-**
1341
-** A "phantom" artifact is an artifact whose hash named appears in some
1342
-** artifact but whose content is unknown. For example, if a manifest
1343
-** references a particular SHA3 hash of a file, but that SHA3 hash is
1344
-** not on the shunning list and is not in the database, then the file
1345
-** is a phantom. We know it exists, but we do not know its content.
1346
-**
1347
-** Whenever a sync occurs, both each party looks at its phantom list
1348
-** and for every phantom that is not also marked private, it asks the
1349
-** other party to send it the content. This mechanism helps keep all
1350
-** repositories synced up.
1351
-**
1352
-** This page is similar to the /bloblist page in that it lists artifacts.
1353
-** But this page is a special case in that it only shows phantoms that
1354
-** are not private. In other words, this page shows all phantoms that
1355
-** generate extra network traffic on every sync request.
1383
+** Output HTML that shows a table of all public phantoms.
13561384
*/
1357
-void phantom_list_page(void){
1385
+void table_of_public_phantoms(void){
13581386
Stmt q;
13591387
char *zRange;
1360
-
1361
- login_check_credentials();
1362
- if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1363
- style_header("Public Phantom Artifacts");
1364
- if( g.perm.Admin ){
1365
- style_submenu_element("Artifact Log", "rcvfromlist");
1366
- style_submenu_element("Artifact List", "bloblist");
1367
- }
1368
- if( g.perm.Write ){
1369
- style_submenu_element("Artifact Stats", "artifact_stats");
1370
- }
13711388
zRange = mprintf("IN (SELECT rid FROM phantom EXCEPT"
13721389
" SELECT rid FROM private)");
13731390
describe_artifacts(zRange);
13741391
fossil_free(zRange);
13751392
db_prepare(&q,
@@ -1392,10 +1409,45 @@
13921409
}
13931410
@ </tr>
13941411
}
13951412
@ </table>
13961413
db_finalize(&q);
1414
+}
1415
+
1416
+/*
1417
+** WEBPAGE: phantoms
1418
+**
1419
+** Show a list of all "phantom" artifacts that are not marked as "private".
1420
+**
1421
+** A "phantom" artifact is an artifact whose hash named appears in some
1422
+** artifact but whose content is unknown. For example, if a manifest
1423
+** references a particular SHA3 hash of a file, but that SHA3 hash is
1424
+** not on the shunning list and is not in the database, then the file
1425
+** is a phantom. We know it exists, but we do not know its content.
1426
+**
1427
+** Whenever a sync occurs, both each party looks at its phantom list
1428
+** and for every phantom that is not also marked private, it asks the
1429
+** other party to send it the content. This mechanism helps keep all
1430
+** repositories synced up.
1431
+**
1432
+** This page is similar to the /bloblist page in that it lists artifacts.
1433
+** But this page is a special case in that it only shows phantoms that
1434
+** are not private. In other words, this page shows all phantoms that
1435
+** generate extra network traffic on every sync request.
1436
+*/
1437
+void phantom_list_page(void){
1438
+ login_check_credentials();
1439
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1440
+ style_header("Public Phantom Artifacts");
1441
+ if( g.perm.Admin ){
1442
+ style_submenu_element("Artifact Log", "rcvfromlist");
1443
+ style_submenu_element("Artifact List", "bloblist");
1444
+ }
1445
+ if( g.perm.Write ){
1446
+ style_submenu_element("Artifact Stats", "artifact_stats");
1447
+ }
1448
+ table_of_public_phantoms();
13971449
style_footer();
13981450
}
13991451
14001452
/*
14011453
** WEBPAGE: bigbloblist
14021454
--- src/name.c
+++ src/name.c
@@ -968,10 +968,75 @@
968 @ summary TEXT, -- Summary comment for the object
969 @ ref TEXT -- hash of an object to link against
970 @ );
971 @ CREATE INDEX desctype ON description(summary) WHERE summary='unknown';
972 ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
974 /*
975 ** Create the description table if it does not already exists.
976 ** Populate fields of this table with descriptions for all artifacts
977 ** whose RID matches the SQL expression in zWhere.
@@ -1120,32 +1185,13 @@
1120 /* Mark private elements */
1121 db_multi_exec(
1122 "UPDATE description SET isPrivate=1 WHERE rid IN private"
1123 );
1124
1125 /* Try to figure out the origin of unknown artifacts */
1126 db_multi_exec(
1127 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1128 " SELECT description.rid, description.uuid, isPrivate, type,\n"
1129 " CASE WHEN plink.isprim THEN '' ELSE 'merge ' END ||\n"
1130 " 'parent of check-in', blob.uuid\n"
1131 " FROM description, plink, blob\n"
1132 " WHERE description.summary='unknown'\n"
1133 " AND plink.pid=description.rid\n"
1134 " AND blob.rid=plink.cid;"
1135 );
1136 db_multi_exec(
1137 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1138 " SELECT description.rid, description.uuid, isPrivate, type,\n"
1139 " 'check-in referenced by \"'||tag.tagname ||'\" tag',\n"
1140 " blob.uuid\n"
1141 " FROM description, tagxref, tag, blob\n"
1142 " WHERE description.summary='unknown'\n"
1143 " AND tagxref.origid=description.rid\n"
1144 " AND tag.tagid=tagxref.tagid\n"
1145 " AND blob.rid=tagxref.srcid;"
1146 );
1147 }
1148
1149 /*
1150 ** Print the content of the description table on stdout.
1151 **
@@ -1332,44 +1378,15 @@
1332 db_finalize(&q);
1333 style_footer();
1334 }
1335
1336 /*
1337 ** WEBPAGE: phantoms
1338 **
1339 ** Show a list of all "phantom" artifacts that are not marked as "private".
1340 **
1341 ** A "phantom" artifact is an artifact whose hash named appears in some
1342 ** artifact but whose content is unknown. For example, if a manifest
1343 ** references a particular SHA3 hash of a file, but that SHA3 hash is
1344 ** not on the shunning list and is not in the database, then the file
1345 ** is a phantom. We know it exists, but we do not know its content.
1346 **
1347 ** Whenever a sync occurs, both each party looks at its phantom list
1348 ** and for every phantom that is not also marked private, it asks the
1349 ** other party to send it the content. This mechanism helps keep all
1350 ** repositories synced up.
1351 **
1352 ** This page is similar to the /bloblist page in that it lists artifacts.
1353 ** But this page is a special case in that it only shows phantoms that
1354 ** are not private. In other words, this page shows all phantoms that
1355 ** generate extra network traffic on every sync request.
1356 */
1357 void phantom_list_page(void){
1358 Stmt q;
1359 char *zRange;
1360
1361 login_check_credentials();
1362 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1363 style_header("Public Phantom Artifacts");
1364 if( g.perm.Admin ){
1365 style_submenu_element("Artifact Log", "rcvfromlist");
1366 style_submenu_element("Artifact List", "bloblist");
1367 }
1368 if( g.perm.Write ){
1369 style_submenu_element("Artifact Stats", "artifact_stats");
1370 }
1371 zRange = mprintf("IN (SELECT rid FROM phantom EXCEPT"
1372 " SELECT rid FROM private)");
1373 describe_artifacts(zRange);
1374 fossil_free(zRange);
1375 db_prepare(&q,
@@ -1392,10 +1409,45 @@
1392 }
1393 @ </tr>
1394 }
1395 @ </table>
1396 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1397 style_footer();
1398 }
1399
1400 /*
1401 ** WEBPAGE: bigbloblist
1402
--- src/name.c
+++ src/name.c
@@ -968,10 +968,75 @@
968 @ summary TEXT, -- Summary comment for the object
969 @ ref TEXT -- hash of an object to link against
970 @ );
971 @ CREATE INDEX desctype ON description(summary) WHERE summary='unknown';
972 ;
973
974 /*
975 ** Attempt to describe all phantom artifacts. The artifacts are
976 ** already loaded into the description table and have summary='unknown'.
977 ** This routine attempts to generate a better summary, and possibly
978 ** fill in the ref field.
979 */
980 static void describe_unknown_artifacts(){
981 /* Try to figure out the origin of unknown artifacts */
982 db_multi_exec(
983 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
984 " SELECT description.rid, description.uuid, isPrivate, type,\n"
985 " CASE WHEN plink.isprim THEN '' ELSE 'merge ' END ||\n"
986 " 'parent of check-in', blob.uuid\n"
987 " FROM description, plink, blob\n"
988 " WHERE description.summary='unknown'\n"
989 " AND plink.pid=description.rid\n"
990 " AND blob.rid=plink.cid;"
991 );
992 db_multi_exec(
993 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
994 " SELECT description.rid, description.uuid, isPrivate, type,\n"
995 " 'child of check-in', blob.uuid\n"
996 " FROM description, plink, blob\n"
997 " WHERE description.summary='unknown'\n"
998 " AND plink.cid=description.rid\n"
999 " AND blob.rid=plink.pid;"
1000 );
1001 db_multi_exec(
1002 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1003 " SELECT description.rid, description.uuid, isPrivate, type,\n"
1004 " 'check-in referenced by \"'||tag.tagname ||'\" tag',\n"
1005 " blob.uuid\n"
1006 " FROM description, tagxref, tag, blob\n"
1007 " WHERE description.summary='unknown'\n"
1008 " AND tagxref.origid=description.rid\n"
1009 " AND tag.tagid=tagxref.tagid\n"
1010 " AND blob.rid=tagxref.srcid;"
1011 );
1012 db_multi_exec(
1013 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1014 " SELECT description.rid, description.uuid, isPrivate, type,\n"
1015 " 'file \"'||filename.name||'\"',\n"
1016 " blob.uuid\n"
1017 " FROM description, mlink, filename, blob\n"
1018 " WHERE description.summary='unknown'\n"
1019 " AND mlink.fid=description.rid\n"
1020 " AND blob.rid=mlink.mid\n"
1021 " AND filename.fnid=mlink.fnid;"
1022 );
1023 if( !db_exists("SELECT 1 FROM description WHERE summary='unknown'") ){
1024 return;
1025 }
1026 add_content_sql_commands(g.db);
1027 db_multi_exec(
1028 "REPLACE INTO description(rid,uuid,isPrivate,type,summary,ref)\n"
1029 " SELECT description.rid, description.uuid, isPrivate, type,\n"
1030 " 'referenced by cluster', blob.uuid\n"
1031 " FROM description, tagxref, blob\n"
1032 " WHERE description.summary='unknown'\n"
1033 " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
1034 " AND blob.rid=tagxref.rid\n"
1035 " AND content(blob.uuid) GLOB ('*M '||blob.uuid||'*');"
1036 );
1037 }
1038
1039 /*
1040 ** Create the description table if it does not already exists.
1041 ** Populate fields of this table with descriptions for all artifacts
1042 ** whose RID matches the SQL expression in zWhere.
@@ -1120,32 +1185,13 @@
1185 /* Mark private elements */
1186 db_multi_exec(
1187 "UPDATE description SET isPrivate=1 WHERE rid IN private"
1188 );
1189
1190 if( db_exists("SELECT 1 FROM description WHERE summary='unknown'") ){
1191 describe_unknown_artifacts();
1192 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1193 }
1194
1195 /*
1196 ** Print the content of the description table on stdout.
1197 **
@@ -1332,44 +1378,15 @@
1378 db_finalize(&q);
1379 style_footer();
1380 }
1381
1382 /*
1383 ** Output HTML that shows a table of all public phantoms.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1384 */
1385 void table_of_public_phantoms(void){
1386 Stmt q;
1387 char *zRange;
 
 
 
 
 
 
 
 
 
 
 
1388 zRange = mprintf("IN (SELECT rid FROM phantom EXCEPT"
1389 " SELECT rid FROM private)");
1390 describe_artifacts(zRange);
1391 fossil_free(zRange);
1392 db_prepare(&q,
@@ -1392,10 +1409,45 @@
1409 }
1410 @ </tr>
1411 }
1412 @ </table>
1413 db_finalize(&q);
1414 }
1415
1416 /*
1417 ** WEBPAGE: phantoms
1418 **
1419 ** Show a list of all "phantom" artifacts that are not marked as "private".
1420 **
1421 ** A "phantom" artifact is an artifact whose hash named appears in some
1422 ** artifact but whose content is unknown. For example, if a manifest
1423 ** references a particular SHA3 hash of a file, but that SHA3 hash is
1424 ** not on the shunning list and is not in the database, then the file
1425 ** is a phantom. We know it exists, but we do not know its content.
1426 **
1427 ** Whenever a sync occurs, both each party looks at its phantom list
1428 ** and for every phantom that is not also marked private, it asks the
1429 ** other party to send it the content. This mechanism helps keep all
1430 ** repositories synced up.
1431 **
1432 ** This page is similar to the /bloblist page in that it lists artifacts.
1433 ** But this page is a special case in that it only shows phantoms that
1434 ** are not private. In other words, this page shows all phantoms that
1435 ** generate extra network traffic on every sync request.
1436 */
1437 void phantom_list_page(void){
1438 login_check_credentials();
1439 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1440 style_header("Public Phantom Artifacts");
1441 if( g.perm.Admin ){
1442 style_submenu_element("Artifact Log", "rcvfromlist");
1443 style_submenu_element("Artifact List", "bloblist");
1444 }
1445 if( g.perm.Write ){
1446 style_submenu_element("Artifact Stats", "artifact_stats");
1447 }
1448 table_of_public_phantoms();
1449 style_footer();
1450 }
1451
1452 /*
1453 ** WEBPAGE: bigbloblist
1454
--- src/security_audit.c
+++ src/security_audit.c
@@ -558,22 +558,19 @@
558558
559559
n = db_int(0,"SELECT count(*) FROM ("
560560
"SELECT rid FROM phantom EXCEPT SELECT rid FROM private)");
561561
if( n>0 ){
562562
@ <li><p>\
563
- if( n==1 ){
564
- @ There is 1 public phantom artifact
565
- }else{
566
- @ There are %d(n) public phantom artifacts
567
- }
568
- @ (<a href="%R/phantoms">details</a>).
563
+ @ There exists public phantom artifacts in this repository, shown below.
569564
@ Phantom artifacts are artifacts whose hash name is referenced by some
570565
@ other artifact but whose content is unknown. Some phantoms are marked
571566
@ private and those are ignored. But public phantoms cause unnecessary
572567
@ sync traffic and might represent malicious attempts to corrupt the
573568
@ repository structure.
574
- @ </p></li>
569
+ @ </p>
570
+ table_of_public_phantoms();
571
+ @ </li>
575572
}
576573
577574
@ </ol>
578575
style_footer();
579576
}
580577
--- src/security_audit.c
+++ src/security_audit.c
@@ -558,22 +558,19 @@
558
559 n = db_int(0,"SELECT count(*) FROM ("
560 "SELECT rid FROM phantom EXCEPT SELECT rid FROM private)");
561 if( n>0 ){
562 @ <li><p>\
563 if( n==1 ){
564 @ There is 1 public phantom artifact
565 }else{
566 @ There are %d(n) public phantom artifacts
567 }
568 @ (<a href="%R/phantoms">details</a>).
569 @ Phantom artifacts are artifacts whose hash name is referenced by some
570 @ other artifact but whose content is unknown. Some phantoms are marked
571 @ private and those are ignored. But public phantoms cause unnecessary
572 @ sync traffic and might represent malicious attempts to corrupt the
573 @ repository structure.
574 @ </p></li>
 
 
575 }
576
577 @ </ol>
578 style_footer();
579 }
580
--- src/security_audit.c
+++ src/security_audit.c
@@ -558,22 +558,19 @@
558
559 n = db_int(0,"SELECT count(*) FROM ("
560 "SELECT rid FROM phantom EXCEPT SELECT rid FROM private)");
561 if( n>0 ){
562 @ <li><p>\
563 @ There exists public phantom artifacts in this repository, shown below.
 
 
 
 
 
564 @ Phantom artifacts are artifacts whose hash name is referenced by some
565 @ other artifact but whose content is unknown. Some phantoms are marked
566 @ private and those are ignored. But public phantoms cause unnecessary
567 @ sync traffic and might represent malicious attempts to corrupt the
568 @ repository structure.
569 @ </p>
570 table_of_public_phantoms();
571 @ </li>
572 }
573
574 @ </ol>
575 style_footer();
576 }
577

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button