Fossil SCM
Enable access to the ".well-known" subdirectory, to facilitate ACME.
Commit
6d447b8669d9286b889dc8e02ab4acefd7c454417641cf2beba9cb46bc3bdc5c
Parent
f6051784c5eef73…
1 file changed
+72
-9
+72
-9
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -855,10 +855,14 @@ | ||
| 855 | 855 | ** This command is used to view or modify the TLS (Transport Layer |
| 856 | 856 | ** Security) configuration for Fossil. TLS (formerly SSL) is the |
| 857 | 857 | ** encryption technology used for secure HTTPS transport. |
| 858 | 858 | ** |
| 859 | 859 | ** Sub-commands: |
| 860 | +** | |
| 861 | +** acme ON/OFF Activate or deactivate web access to files in | |
| 862 | +** the "./well-known" directory. This must be on | |
| 863 | +** to support "certbot". | |
| 860 | 864 | ** |
| 861 | 865 | ** clear-cert Remove information about server certificates. |
| 862 | 866 | ** This is a subset of the "scrub" command. |
| 863 | 867 | ** |
| 864 | 868 | ** load-cert PEM-FILES... Identify server certificate files. These |
| @@ -879,13 +883,10 @@ | ||
| 879 | 883 | ** |
| 880 | 884 | ** show ?-v? Show the TLS configuration. Add -v to see |
| 881 | 885 | ** additional explaination |
| 882 | 886 | */ |
| 883 | 887 | void test_tlsconfig_info(void){ |
| 884 | -#if !defined(FOSSIL_ENABLE_SSL) | |
| 885 | - fossil_print("TLS disabled in this build\n"); | |
| 886 | -#else | |
| 887 | 888 | const char *zCmd; |
| 888 | 889 | size_t nCmd; |
| 889 | 890 | int nHit = 0; |
| 890 | 891 | db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); |
| 891 | 892 | db_open_config(1,0); |
| @@ -894,10 +895,22 @@ | ||
| 894 | 895 | nCmd = 4; |
| 895 | 896 | }else{ |
| 896 | 897 | zCmd = g.argv[2]; |
| 897 | 898 | nCmd = strlen(zCmd); |
| 898 | 899 | } |
| 900 | + if( strncmp("acme",zCmd,nCmd)==0 ){ | |
| 901 | + if( g.argc!=4 ) usage("acme ON/OFF"); | |
| 902 | + db_unprotect(PROTECT_CONFIG); | |
| 903 | + if( is_truth(g.argv[3]) ){ | |
| 904 | + db_set_int("ssl-acme",1,0); | |
| 905 | + }else if( is_false(g.argv[3]) ){ | |
| 906 | + db_unset("ssl-acme",0); | |
| 907 | + }else{ | |
| 908 | + fossil_fatal("unknown argument: \"%s\"", g.argv[3]); | |
| 909 | + } | |
| 910 | + db_protect_pop(); | |
| 911 | + }else | |
| 899 | 912 | if( strncmp("clear-cert",zCmd,nCmd)==0 && nCmd>=4 ){ |
| 900 | 913 | int bForce = find_option("force","f",0)!=0; |
| 901 | 914 | verify_all_options(); |
| 902 | 915 | if( !bForce ){ |
| 903 | 916 | Blob ans; |
| @@ -1014,10 +1027,18 @@ | ||
| 1014 | 1027 | size_t nName; |
| 1015 | 1028 | Stmt q; |
| 1016 | 1029 | int verbose = find_option("verbose","v",0)!=0; |
| 1017 | 1030 | verify_all_options(); |
| 1018 | 1031 | |
| 1032 | +#if !defined(FOSSIL_ENABLE_SSL) | |
| 1033 | + fossil_print("OpenSSL-version: (none)\n"); | |
| 1034 | + if( verbose ){ | |
| 1035 | + fossil_print("\n" | |
| 1036 | + " The OpenSSL library is not used by this build of Fossil\n\n" | |
| 1037 | + ); | |
| 1038 | + } | |
| 1039 | +#else | |
| 1019 | 1040 | fossil_print("OpenSSL-version: %s (0x%09x)\n", |
| 1020 | 1041 | SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER); |
| 1021 | 1042 | if( verbose ){ |
| 1022 | 1043 | fossil_print("\n" |
| 1023 | 1044 | " The version of the OpenSSL library being used\n" |
| @@ -1048,16 +1069,17 @@ | ||
| 1048 | 1069 | if( zValue==0 ) zValue = ""; |
| 1049 | 1070 | nName = strlen(zName); |
| 1050 | 1071 | fossil_print("%s:%*s%s\n", zName, 18-nName, "", zValue); |
| 1051 | 1072 | if( verbose ){ |
| 1052 | 1073 | fossil_print("\n" |
| 1053 | - " Alternative locations for the root certificates used by Fossil\n" | |
| 1054 | - " when it is acting as a SSL client in order to verify the identity\n" | |
| 1055 | - " of servers. If specified, these alternative locations override\n" | |
| 1056 | - " the built-in locations.\n\n" | |
| 1074 | + " Alternative locations for the root certificates used by Fossil\n" | |
| 1075 | + " when it is acting as a SSL client in order to verify the identity\n" | |
| 1076 | + " of servers. If specified, these alternative locations override\n" | |
| 1077 | + " the built-in locations.\n\n" | |
| 1057 | 1078 | ); |
| 1058 | 1079 | } |
| 1080 | +#endif /* FOSSIL_ENABLE_SSL */ | |
| 1059 | 1081 | |
| 1060 | 1082 | fossil_print("ssl-ca-location: %s\n", db_get("ssl-ca-location","")); |
| 1061 | 1083 | if( verbose ){ |
| 1062 | 1084 | fossil_print("\n" |
| 1063 | 1085 | " This setting is the name of a file or directory that contains\n" |
| @@ -1074,10 +1096,21 @@ | ||
| 1074 | 1096 | " certificate and private-key used by Fossil clients to authentice\n" |
| 1075 | 1097 | " with servers. Few servers actually require this, so this setting\n" |
| 1076 | 1098 | " is usually blank.\n\n" |
| 1077 | 1099 | ); |
| 1078 | 1100 | } |
| 1101 | + | |
| 1102 | + fossil_print("ssl-acme: %s\n", | |
| 1103 | + db_get_boolean("ssl-acme",0) ? "on" : "off"); | |
| 1104 | + if( verbose ){ | |
| 1105 | + fossil_print("\n" | |
| 1106 | + " This setting enables web access to files in the \".well-known\"" | |
| 1107 | + " subdirectory in the same directory as the repository. Such access\n" | |
| 1108 | + " is required to obtain a certificate from services like\n" | |
| 1109 | + " \"Let's Encrypt\" using the tools like \"certbot\".\n\n" | |
| 1110 | + ); | |
| 1111 | + } | |
| 1079 | 1112 | |
| 1080 | 1113 | zValue = db_get("ssl-cert",0); |
| 1081 | 1114 | if( zValue ){ |
| 1082 | 1115 | fossil_print("ssl-cert: (%d-byte PEM)\n", (int)strlen(zValue)); |
| 1083 | 1116 | }else{ |
| @@ -1163,10 +1196,40 @@ | ||
| 1163 | 1196 | db_commit_transaction(); |
| 1164 | 1197 | blob_reset(&sql); |
| 1165 | 1198 | }else |
| 1166 | 1199 | /*default*/{ |
| 1167 | 1200 | fossil_fatal("unknown sub-command \"%s\".\nshould be one of:" |
| 1168 | - " load-certs remove-exception scrub show", | |
| 1201 | + " clear-certs load-certs remove-exception scrub show", | |
| 1169 | 1202 | zCmd); |
| 1170 | 1203 | } |
| 1171 | -#endif | |
| 1204 | +} | |
| 1205 | + | |
| 1206 | +/* | |
| 1207 | +** WEBPAGE: .well-known | |
| 1208 | +** | |
| 1209 | +** If the "ssl-acme" setting is true, then this page returns the content | |
| 1210 | +** of files found in the ".well-known" subdirectory of the same directory | |
| 1211 | +** that contains the repository file. This facilitates Automated Certificate | |
| 1212 | +** Management using tools like "certbot". | |
| 1213 | +** | |
| 1214 | +** The content is returned directly, without any interpretation, using | |
| 1215 | +** a generic mimetype. | |
| 1216 | +*/ | |
| 1217 | +void wellknown_page(void){ | |
| 1218 | + char *zPath; | |
| 1219 | + const char *zTail = P("name"); | |
| 1220 | + Blob content; | |
| 1221 | + if( !db_get_boolean("ssl-acme",0) ) goto wellknown_notfound; | |
| 1222 | + if( g.zRepositoryName==0 ) goto wellknown_notfound; | |
| 1223 | + if( zTail==0 ) goto wellknown_notfound; | |
| 1224 | + zPath = mprintf("%z/.well-known/%s", file_dirname(g.zRepositoryName), zTail); | |
| 1225 | + if( !file_isfile(zPath, ExtFILE) ) goto wellknown_notfound; | |
| 1226 | + blob_read_from_file(&content, zPath, ExtFILE); | |
| 1227 | + cgi_set_content(&content); | |
| 1228 | + cgi_set_content_type(mimetype_from_name(zPath)); | |
| 1229 | + cgi_reply(); | |
| 1230 | + return; | |
| 1231 | + | |
| 1232 | +wellknown_notfound: | |
| 1233 | + webpage_notfound_error(0); | |
| 1234 | + return; | |
| 1172 | 1235 | } |
| 1173 | 1236 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -855,10 +855,14 @@ | |
| 855 | ** This command is used to view or modify the TLS (Transport Layer |
| 856 | ** Security) configuration for Fossil. TLS (formerly SSL) is the |
| 857 | ** encryption technology used for secure HTTPS transport. |
| 858 | ** |
| 859 | ** Sub-commands: |
| 860 | ** |
| 861 | ** clear-cert Remove information about server certificates. |
| 862 | ** This is a subset of the "scrub" command. |
| 863 | ** |
| 864 | ** load-cert PEM-FILES... Identify server certificate files. These |
| @@ -879,13 +883,10 @@ | |
| 879 | ** |
| 880 | ** show ?-v? Show the TLS configuration. Add -v to see |
| 881 | ** additional explaination |
| 882 | */ |
| 883 | void test_tlsconfig_info(void){ |
| 884 | #if !defined(FOSSIL_ENABLE_SSL) |
| 885 | fossil_print("TLS disabled in this build\n"); |
| 886 | #else |
| 887 | const char *zCmd; |
| 888 | size_t nCmd; |
| 889 | int nHit = 0; |
| 890 | db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); |
| 891 | db_open_config(1,0); |
| @@ -894,10 +895,22 @@ | |
| 894 | nCmd = 4; |
| 895 | }else{ |
| 896 | zCmd = g.argv[2]; |
| 897 | nCmd = strlen(zCmd); |
| 898 | } |
| 899 | if( strncmp("clear-cert",zCmd,nCmd)==0 && nCmd>=4 ){ |
| 900 | int bForce = find_option("force","f",0)!=0; |
| 901 | verify_all_options(); |
| 902 | if( !bForce ){ |
| 903 | Blob ans; |
| @@ -1014,10 +1027,18 @@ | |
| 1014 | size_t nName; |
| 1015 | Stmt q; |
| 1016 | int verbose = find_option("verbose","v",0)!=0; |
| 1017 | verify_all_options(); |
| 1018 | |
| 1019 | fossil_print("OpenSSL-version: %s (0x%09x)\n", |
| 1020 | SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER); |
| 1021 | if( verbose ){ |
| 1022 | fossil_print("\n" |
| 1023 | " The version of the OpenSSL library being used\n" |
| @@ -1048,16 +1069,17 @@ | |
| 1048 | if( zValue==0 ) zValue = ""; |
| 1049 | nName = strlen(zName); |
| 1050 | fossil_print("%s:%*s%s\n", zName, 18-nName, "", zValue); |
| 1051 | if( verbose ){ |
| 1052 | fossil_print("\n" |
| 1053 | " Alternative locations for the root certificates used by Fossil\n" |
| 1054 | " when it is acting as a SSL client in order to verify the identity\n" |
| 1055 | " of servers. If specified, these alternative locations override\n" |
| 1056 | " the built-in locations.\n\n" |
| 1057 | ); |
| 1058 | } |
| 1059 | |
| 1060 | fossil_print("ssl-ca-location: %s\n", db_get("ssl-ca-location","")); |
| 1061 | if( verbose ){ |
| 1062 | fossil_print("\n" |
| 1063 | " This setting is the name of a file or directory that contains\n" |
| @@ -1074,10 +1096,21 @@ | |
| 1074 | " certificate and private-key used by Fossil clients to authentice\n" |
| 1075 | " with servers. Few servers actually require this, so this setting\n" |
| 1076 | " is usually blank.\n\n" |
| 1077 | ); |
| 1078 | } |
| 1079 | |
| 1080 | zValue = db_get("ssl-cert",0); |
| 1081 | if( zValue ){ |
| 1082 | fossil_print("ssl-cert: (%d-byte PEM)\n", (int)strlen(zValue)); |
| 1083 | }else{ |
| @@ -1163,10 +1196,40 @@ | |
| 1163 | db_commit_transaction(); |
| 1164 | blob_reset(&sql); |
| 1165 | }else |
| 1166 | /*default*/{ |
| 1167 | fossil_fatal("unknown sub-command \"%s\".\nshould be one of:" |
| 1168 | " load-certs remove-exception scrub show", |
| 1169 | zCmd); |
| 1170 | } |
| 1171 | #endif |
| 1172 | } |
| 1173 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -855,10 +855,14 @@ | |
| 855 | ** This command is used to view or modify the TLS (Transport Layer |
| 856 | ** Security) configuration for Fossil. TLS (formerly SSL) is the |
| 857 | ** encryption technology used for secure HTTPS transport. |
| 858 | ** |
| 859 | ** Sub-commands: |
| 860 | ** |
| 861 | ** acme ON/OFF Activate or deactivate web access to files in |
| 862 | ** the "./well-known" directory. This must be on |
| 863 | ** to support "certbot". |
| 864 | ** |
| 865 | ** clear-cert Remove information about server certificates. |
| 866 | ** This is a subset of the "scrub" command. |
| 867 | ** |
| 868 | ** load-cert PEM-FILES... Identify server certificate files. These |
| @@ -879,13 +883,10 @@ | |
| 883 | ** |
| 884 | ** show ?-v? Show the TLS configuration. Add -v to see |
| 885 | ** additional explaination |
| 886 | */ |
| 887 | void test_tlsconfig_info(void){ |
| 888 | const char *zCmd; |
| 889 | size_t nCmd; |
| 890 | int nHit = 0; |
| 891 | db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); |
| 892 | db_open_config(1,0); |
| @@ -894,10 +895,22 @@ | |
| 895 | nCmd = 4; |
| 896 | }else{ |
| 897 | zCmd = g.argv[2]; |
| 898 | nCmd = strlen(zCmd); |
| 899 | } |
| 900 | if( strncmp("acme",zCmd,nCmd)==0 ){ |
| 901 | if( g.argc!=4 ) usage("acme ON/OFF"); |
| 902 | db_unprotect(PROTECT_CONFIG); |
| 903 | if( is_truth(g.argv[3]) ){ |
| 904 | db_set_int("ssl-acme",1,0); |
| 905 | }else if( is_false(g.argv[3]) ){ |
| 906 | db_unset("ssl-acme",0); |
| 907 | }else{ |
| 908 | fossil_fatal("unknown argument: \"%s\"", g.argv[3]); |
| 909 | } |
| 910 | db_protect_pop(); |
| 911 | }else |
| 912 | if( strncmp("clear-cert",zCmd,nCmd)==0 && nCmd>=4 ){ |
| 913 | int bForce = find_option("force","f",0)!=0; |
| 914 | verify_all_options(); |
| 915 | if( !bForce ){ |
| 916 | Blob ans; |
| @@ -1014,10 +1027,18 @@ | |
| 1027 | size_t nName; |
| 1028 | Stmt q; |
| 1029 | int verbose = find_option("verbose","v",0)!=0; |
| 1030 | verify_all_options(); |
| 1031 | |
| 1032 | #if !defined(FOSSIL_ENABLE_SSL) |
| 1033 | fossil_print("OpenSSL-version: (none)\n"); |
| 1034 | if( verbose ){ |
| 1035 | fossil_print("\n" |
| 1036 | " The OpenSSL library is not used by this build of Fossil\n\n" |
| 1037 | ); |
| 1038 | } |
| 1039 | #else |
| 1040 | fossil_print("OpenSSL-version: %s (0x%09x)\n", |
| 1041 | SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER); |
| 1042 | if( verbose ){ |
| 1043 | fossil_print("\n" |
| 1044 | " The version of the OpenSSL library being used\n" |
| @@ -1048,16 +1069,17 @@ | |
| 1069 | if( zValue==0 ) zValue = ""; |
| 1070 | nName = strlen(zName); |
| 1071 | fossil_print("%s:%*s%s\n", zName, 18-nName, "", zValue); |
| 1072 | if( verbose ){ |
| 1073 | fossil_print("\n" |
| 1074 | " Alternative locations for the root certificates used by Fossil\n" |
| 1075 | " when it is acting as a SSL client in order to verify the identity\n" |
| 1076 | " of servers. If specified, these alternative locations override\n" |
| 1077 | " the built-in locations.\n\n" |
| 1078 | ); |
| 1079 | } |
| 1080 | #endif /* FOSSIL_ENABLE_SSL */ |
| 1081 | |
| 1082 | fossil_print("ssl-ca-location: %s\n", db_get("ssl-ca-location","")); |
| 1083 | if( verbose ){ |
| 1084 | fossil_print("\n" |
| 1085 | " This setting is the name of a file or directory that contains\n" |
| @@ -1074,10 +1096,21 @@ | |
| 1096 | " certificate and private-key used by Fossil clients to authentice\n" |
| 1097 | " with servers. Few servers actually require this, so this setting\n" |
| 1098 | " is usually blank.\n\n" |
| 1099 | ); |
| 1100 | } |
| 1101 | |
| 1102 | fossil_print("ssl-acme: %s\n", |
| 1103 | db_get_boolean("ssl-acme",0) ? "on" : "off"); |
| 1104 | if( verbose ){ |
| 1105 | fossil_print("\n" |
| 1106 | " This setting enables web access to files in the \".well-known\"" |
| 1107 | " subdirectory in the same directory as the repository. Such access\n" |
| 1108 | " is required to obtain a certificate from services like\n" |
| 1109 | " \"Let's Encrypt\" using the tools like \"certbot\".\n\n" |
| 1110 | ); |
| 1111 | } |
| 1112 | |
| 1113 | zValue = db_get("ssl-cert",0); |
| 1114 | if( zValue ){ |
| 1115 | fossil_print("ssl-cert: (%d-byte PEM)\n", (int)strlen(zValue)); |
| 1116 | }else{ |
| @@ -1163,10 +1196,40 @@ | |
| 1196 | db_commit_transaction(); |
| 1197 | blob_reset(&sql); |
| 1198 | }else |
| 1199 | /*default*/{ |
| 1200 | fossil_fatal("unknown sub-command \"%s\".\nshould be one of:" |
| 1201 | " clear-certs load-certs remove-exception scrub show", |
| 1202 | zCmd); |
| 1203 | } |
| 1204 | } |
| 1205 | |
| 1206 | /* |
| 1207 | ** WEBPAGE: .well-known |
| 1208 | ** |
| 1209 | ** If the "ssl-acme" setting is true, then this page returns the content |
| 1210 | ** of files found in the ".well-known" subdirectory of the same directory |
| 1211 | ** that contains the repository file. This facilitates Automated Certificate |
| 1212 | ** Management using tools like "certbot". |
| 1213 | ** |
| 1214 | ** The content is returned directly, without any interpretation, using |
| 1215 | ** a generic mimetype. |
| 1216 | */ |
| 1217 | void wellknown_page(void){ |
| 1218 | char *zPath; |
| 1219 | const char *zTail = P("name"); |
| 1220 | Blob content; |
| 1221 | if( !db_get_boolean("ssl-acme",0) ) goto wellknown_notfound; |
| 1222 | if( g.zRepositoryName==0 ) goto wellknown_notfound; |
| 1223 | if( zTail==0 ) goto wellknown_notfound; |
| 1224 | zPath = mprintf("%z/.well-known/%s", file_dirname(g.zRepositoryName), zTail); |
| 1225 | if( !file_isfile(zPath, ExtFILE) ) goto wellknown_notfound; |
| 1226 | blob_read_from_file(&content, zPath, ExtFILE); |
| 1227 | cgi_set_content(&content); |
| 1228 | cgi_set_content_type(mimetype_from_name(zPath)); |
| 1229 | cgi_reply(); |
| 1230 | return; |
| 1231 | |
| 1232 | wellknown_notfound: |
| 1233 | webpage_notfound_error(0); |
| 1234 | return; |
| 1235 | } |
| 1236 |