Fossil SCM
Start the security audit by checking to see if the repos it public or private.
Commit
7f29e2640ab5d1dc7271dad859c608bcc335ff753ebd9eacc66501c31b3bc4c5
Parent
c550402982cc975…
1 file changed
+103
-1
+103
-1
| --- src/security_audit.c | ||
| +++ src/security_audit.c | ||
| @@ -20,22 +20,124 @@ | ||
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 23 | #include "security_audit.h" |
| 24 | 24 | |
| 25 | +/* | |
| 26 | +** Return TRUE if any of the capability letters in zTest are found | |
| 27 | +** in the capability string zCap. | |
| 28 | +*/ | |
| 29 | +static int hasAnyCap(const char *zCap, const char *zTest){ | |
| 30 | + while( zTest[0] ){ | |
| 31 | + if( strchr(zCap, zTest[0]) ) return 1; | |
| 32 | + zTest++; | |
| 33 | + } | |
| 34 | + return 0; | |
| 35 | +} | |
| 36 | + | |
| 25 | 37 | |
| 26 | 38 | /* |
| 27 | 39 | ** WEBPAGE: secaudit0 |
| 28 | 40 | ** |
| 29 | 41 | ** Run a security audit of the current Fossil setup. |
| 30 | 42 | ** This page requires administrator access |
| 31 | 43 | */ |
| 32 | 44 | void secaudit0_page(void){ |
| 45 | + const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */ | |
| 46 | + const char *zPubPages; /* GLOB pattern for public pages */ | |
| 47 | + | |
| 33 | 48 | login_check_credentials(); |
| 34 | 49 | if( !g.perm.Setup && !g.perm.Admin ){ |
| 35 | 50 | login_needed(0); |
| 36 | 51 | return; |
| 37 | 52 | } |
| 38 | 53 | style_header("Security Audit"); |
| 39 | - @ Under Construction... | |
| 54 | + @ <ol> | |
| 55 | + | |
| 56 | + /* Step 1: Determine if the repository is public or private. "Public" | |
| 57 | + ** means that any anonymous user on the internet can access all content. | |
| 58 | + ** "Private" repos require (non-anonymous) login to access all content, | |
| 59 | + ** though some content may be accessible anonymously. | |
| 60 | + */ | |
| 61 | + zAnonCap = db_text("", "SELECT group_concat(coalesce(cap,'')) FROM user" | |
| 62 | + " WHERE login IN ('anonymous','nobody')"); | |
| 63 | + zPubPages = db_get("public-pages",0); | |
| 64 | + if( hasAnyCap(zAnonCap,"as") ){ | |
| 65 | + @ <li><p>This repository is <big><b>Wildly INSECURE</b></big> because | |
| 66 | + @ it grants administrator privileges to anonymous users. You | |
| 67 | + @ should <a href="takeitprivate">take this repository private</a> | |
| 68 | + @ immediately! Or, at least remove the Setup and Admin privileges | |
| 69 | + @ for users "anonymous" and "login" on the | |
| 70 | + @ <a href="setup_ulist">User Configuration</a> page. | |
| 71 | + }else if( hasAnyCap(zAnonCap,"y") ){ | |
| 72 | + @ <li><p>This repository is <big><b>INSECURE</b></big> because | |
| 73 | + @ it allows anonymous users to push unversioned files. You can | |
| 74 | + @ fix this by <a href="takeitprivate">taking the repository private</a> | |
| 75 | + @ or by removing the "y" permission from users "anonymous" and | |
| 76 | + @ "nobody" on the <a href="setup_ulist">User Configuration</a> page. | |
| 77 | + }else if( hasAnyCap(zAnonCap,"goz") ){ | |
| 78 | + @ <li><p>This repository is <big><b>PUBLIC</b></big>. All | |
| 79 | + @ checked-in content can be accessed by anonymous passers-by on the | |
| 80 | + @ internet. <a href="takeitprivate">Take it private</a>.<p> | |
| 81 | + }else if( !hasAnyCap(zAnonCap, "jry") && (zPubPages==0 || zPubPages[0]==0) ){ | |
| 82 | + @ <li><p>This repository is <big><b>Completely PRIVATE</b></big>. | |
| 83 | + @ A valid login and password is required to access any content. | |
| 84 | + }else{ | |
| 85 | + @ <li><p>This repository is <big><b>Mostly PRIVATE</b></big>. | |
| 86 | + @ A valid login and password is usually required, however some | |
| 87 | + @ content can be accessed anonymously: | |
| 88 | + @ <ul> | |
| 89 | + if( zPubPages && zPubPages[0] ){ | |
| 90 | + @ <li> URLs that matches one of these GLOB patterns: | |
| 91 | + @ "%h(zPubPages)" (Change this using the "Public pages" setting | |
| 92 | + @ on the <a href="setup_access">Access Settings</a> page.) | |
| 93 | + } | |
| 94 | + if( hasAnyCap(zAnonCap,"j") ){ | |
| 95 | + @ <li> Wiki pages | |
| 96 | + } | |
| 97 | + if( hasAnyCap(zAnonCap,"r") ){ | |
| 98 | + @ <li> Tickets | |
| 99 | + } | |
| 100 | + @ </ul> | |
| 101 | + } | |
| 102 | + | |
| 103 | + style_footer(); | |
| 104 | +} | |
| 105 | + | |
| 106 | +/* | |
| 107 | +** WEBPAGE: takeitprivate | |
| 108 | +** | |
| 109 | +** Disable anonymous access to this website | |
| 110 | +*/ | |
| 111 | +void takeitprivate_page(void){ | |
| 112 | + login_check_credentials(); | |
| 113 | + if( !g.perm.Setup && !g.perm.Admin ){ | |
| 114 | + login_needed(0); | |
| 115 | + return; | |
| 116 | + } | |
| 117 | + if( P("cancel") ){ | |
| 118 | + /* User pressed the cancel button. Go back */ | |
| 119 | + cgi_redirect("secaudit0"); | |
| 120 | + } | |
| 121 | + if( P("apply") ){ | |
| 122 | + db_multi_exec( | |
| 123 | + "UPDATE user SET cap=''" | |
| 124 | + " WHERE login IN ('nobody','anonymous');" | |
| 125 | + "DELETE FROM config WHERE name='public-pages';" | |
| 126 | + ); | |
| 127 | + cgi_redirect("secaudit0"); | |
| 128 | + } | |
| 129 | + style_header("Make This Website Private"); | |
| 130 | + @ <p>Click the "Make It Private" button below to disable all | |
| 131 | + @ anonymous access to this repository. A valid login and password | |
| 132 | + @ will be required to access this repository after clicking that | |
| 133 | + @ button.</p> | |
| 134 | + @ | |
| 135 | + @ <p>Click the "Cancel" button to leave things as they are.</p> | |
| 136 | + @ | |
| 137 | + @ <form action="%s(g.zPath)" method="post"> | |
| 138 | + @ <input type="submit" name="apply" value="Make It Private"> | |
| 139 | + @ <input type="submit" name="cancel" value="Cancel"> | |
| 140 | + @ </form> | |
| 141 | + | |
| 40 | 142 | style_footer(); |
| 41 | 143 | } |
| 42 | 144 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -20,22 +20,124 @@ | |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include <assert.h> |
| 23 | #include "security_audit.h" |
| 24 | |
| 25 | |
| 26 | /* |
| 27 | ** WEBPAGE: secaudit0 |
| 28 | ** |
| 29 | ** Run a security audit of the current Fossil setup. |
| 30 | ** This page requires administrator access |
| 31 | */ |
| 32 | void secaudit0_page(void){ |
| 33 | login_check_credentials(); |
| 34 | if( !g.perm.Setup && !g.perm.Admin ){ |
| 35 | login_needed(0); |
| 36 | return; |
| 37 | } |
| 38 | style_header("Security Audit"); |
| 39 | @ Under Construction... |
| 40 | style_footer(); |
| 41 | } |
| 42 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -20,22 +20,124 @@ | |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include <assert.h> |
| 23 | #include "security_audit.h" |
| 24 | |
| 25 | /* |
| 26 | ** Return TRUE if any of the capability letters in zTest are found |
| 27 | ** in the capability string zCap. |
| 28 | */ |
| 29 | static int hasAnyCap(const char *zCap, const char *zTest){ |
| 30 | while( zTest[0] ){ |
| 31 | if( strchr(zCap, zTest[0]) ) return 1; |
| 32 | zTest++; |
| 33 | } |
| 34 | return 0; |
| 35 | } |
| 36 | |
| 37 | |
| 38 | /* |
| 39 | ** WEBPAGE: secaudit0 |
| 40 | ** |
| 41 | ** Run a security audit of the current Fossil setup. |
| 42 | ** This page requires administrator access |
| 43 | */ |
| 44 | void secaudit0_page(void){ |
| 45 | const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */ |
| 46 | const char *zPubPages; /* GLOB pattern for public pages */ |
| 47 | |
| 48 | login_check_credentials(); |
| 49 | if( !g.perm.Setup && !g.perm.Admin ){ |
| 50 | login_needed(0); |
| 51 | return; |
| 52 | } |
| 53 | style_header("Security Audit"); |
| 54 | @ <ol> |
| 55 | |
| 56 | /* Step 1: Determine if the repository is public or private. "Public" |
| 57 | ** means that any anonymous user on the internet can access all content. |
| 58 | ** "Private" repos require (non-anonymous) login to access all content, |
| 59 | ** though some content may be accessible anonymously. |
| 60 | */ |
| 61 | zAnonCap = db_text("", "SELECT group_concat(coalesce(cap,'')) FROM user" |
| 62 | " WHERE login IN ('anonymous','nobody')"); |
| 63 | zPubPages = db_get("public-pages",0); |
| 64 | if( hasAnyCap(zAnonCap,"as") ){ |
| 65 | @ <li><p>This repository is <big><b>Wildly INSECURE</b></big> because |
| 66 | @ it grants administrator privileges to anonymous users. You |
| 67 | @ should <a href="takeitprivate">take this repository private</a> |
| 68 | @ immediately! Or, at least remove the Setup and Admin privileges |
| 69 | @ for users "anonymous" and "login" on the |
| 70 | @ <a href="setup_ulist">User Configuration</a> page. |
| 71 | }else if( hasAnyCap(zAnonCap,"y") ){ |
| 72 | @ <li><p>This repository is <big><b>INSECURE</b></big> because |
| 73 | @ it allows anonymous users to push unversioned files. You can |
| 74 | @ fix this by <a href="takeitprivate">taking the repository private</a> |
| 75 | @ or by removing the "y" permission from users "anonymous" and |
| 76 | @ "nobody" on the <a href="setup_ulist">User Configuration</a> page. |
| 77 | }else if( hasAnyCap(zAnonCap,"goz") ){ |
| 78 | @ <li><p>This repository is <big><b>PUBLIC</b></big>. All |
| 79 | @ checked-in content can be accessed by anonymous passers-by on the |
| 80 | @ internet. <a href="takeitprivate">Take it private</a>.<p> |
| 81 | }else if( !hasAnyCap(zAnonCap, "jry") && (zPubPages==0 || zPubPages[0]==0) ){ |
| 82 | @ <li><p>This repository is <big><b>Completely PRIVATE</b></big>. |
| 83 | @ A valid login and password is required to access any content. |
| 84 | }else{ |
| 85 | @ <li><p>This repository is <big><b>Mostly PRIVATE</b></big>. |
| 86 | @ A valid login and password is usually required, however some |
| 87 | @ content can be accessed anonymously: |
| 88 | @ <ul> |
| 89 | if( zPubPages && zPubPages[0] ){ |
| 90 | @ <li> URLs that matches one of these GLOB patterns: |
| 91 | @ "%h(zPubPages)" (Change this using the "Public pages" setting |
| 92 | @ on the <a href="setup_access">Access Settings</a> page.) |
| 93 | } |
| 94 | if( hasAnyCap(zAnonCap,"j") ){ |
| 95 | @ <li> Wiki pages |
| 96 | } |
| 97 | if( hasAnyCap(zAnonCap,"r") ){ |
| 98 | @ <li> Tickets |
| 99 | } |
| 100 | @ </ul> |
| 101 | } |
| 102 | |
| 103 | style_footer(); |
| 104 | } |
| 105 | |
| 106 | /* |
| 107 | ** WEBPAGE: takeitprivate |
| 108 | ** |
| 109 | ** Disable anonymous access to this website |
| 110 | */ |
| 111 | void takeitprivate_page(void){ |
| 112 | login_check_credentials(); |
| 113 | if( !g.perm.Setup && !g.perm.Admin ){ |
| 114 | login_needed(0); |
| 115 | return; |
| 116 | } |
| 117 | if( P("cancel") ){ |
| 118 | /* User pressed the cancel button. Go back */ |
| 119 | cgi_redirect("secaudit0"); |
| 120 | } |
| 121 | if( P("apply") ){ |
| 122 | db_multi_exec( |
| 123 | "UPDATE user SET cap=''" |
| 124 | " WHERE login IN ('nobody','anonymous');" |
| 125 | "DELETE FROM config WHERE name='public-pages';" |
| 126 | ); |
| 127 | cgi_redirect("secaudit0"); |
| 128 | } |
| 129 | style_header("Make This Website Private"); |
| 130 | @ <p>Click the "Make It Private" button below to disable all |
| 131 | @ anonymous access to this repository. A valid login and password |
| 132 | @ will be required to access this repository after clicking that |
| 133 | @ button.</p> |
| 134 | @ |
| 135 | @ <p>Click the "Cancel" button to leave things as they are.</p> |
| 136 | @ |
| 137 | @ <form action="%s(g.zPath)" method="post"> |
| 138 | @ <input type="submit" name="apply" value="Make It Private"> |
| 139 | @ <input type="submit" name="cancel" value="Cancel"> |
| 140 | @ </form> |
| 141 | |
| 142 | style_footer(); |
| 143 | } |
| 144 |