Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Omit the "ssl-acme" setting. Access to ".well-known" is now controlled by the --acme command-line option on "fossil http" and "fossil server". This change is required for when those commands specify a directory rather than a particular repository, since without a specific repository, there are no settings to check. |
|---|---|
| Timelines: | family | ancestors | descendants | both | ssl-server |
| Files: | files | file ages | folders |
| SHA3-256: |
4ef059bc2a73205e19b2f3eeb04f7b4d |
| User & Date: | drh 2021-12-28 19:00:38.745 |
Context
|
2021-12-28
| ||
| 19:04 | Add initial support for SSL (TLS) servers on unix using "fossil server" or "fossil http". Rename the "tls-config" command to "ssl-config". Extend that command to support specifying certificates. Add support for delivering content from the ".well-known" directory to support obtaining certs from Let's Encrypt. check-in: f6263bb641 user: drh tags: trunk | |
| 19:00 | Omit the "ssl-acme" setting. Access to ".well-known" is now controlled by the --acme command-line option on "fossil http" and "fossil server". This change is required for when those commands specify a directory rather than a particular repository, since without a specific repository, there are no settings to check. Closed-Leaf check-in: 4ef059bc2a user: drh tags: ssl-server | |
| 18:17 | Fix the --files option on "fossil http" so that if a glob pattern does not begin with '*' then it will match beginning with the "/" of the PATH_INFO. check-in: 5ac65aa496 user: drh tags: ssl-server | |
Changes
Changes to src/db.c.
| ︙ | ︙ | |||
4262 4263 4264 4265 4266 4267 4268 | ** users can not be deleted. */ /* ** SETTING: ssh-command width=40 sensitive ** The command used to talk to a remote machine with the "ssh://" protocol. */ | < < < < < < < | 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 | ** users can not be deleted. */ /* ** SETTING: ssh-command width=40 sensitive ** The command used to talk to a remote machine with the "ssh://" protocol. */ /* ** SETTING: ssl-ca-location width=40 sensitive ** The full pathname to a file containing PEM encoded ** CA root certificates, or a directory of certificates ** with filenames formed from the certificate hashes as ** required by OpenSSL. ** |
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
854 855 856 857 858 859 860 | ** ** This command is used to view or modify the TLS (Transport Layer ** Security) configuration for Fossil. TLS (formerly SSL) is the ** encryption technology used for secure HTTPS transport. ** ** Sub-commands: ** | < < < < | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | ** ** This command is used to view or modify the TLS (Transport Layer ** Security) configuration for Fossil. TLS (formerly SSL) is the ** encryption technology used for secure HTTPS transport. ** ** Sub-commands: ** ** clear-cert Remove information about server certificates. ** This is a subset of the "scrub" command. ** ** load-cert PEM-FILES... Identify server certificate files. These ** should be in the PEM format. There are ** normally two files, the certificate and the ** private-key. By default, the text of both |
| ︙ | ︙ | |||
893 894 895 896 897 898 899 |
if( g.argc==2 || (g.argc>=3 && g.argv[2][0]=='-') ){
zCmd = "show";
nCmd = 4;
}else{
zCmd = g.argv[2];
nCmd = strlen(zCmd);
}
| < < < < < < < < < < < < | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 |
if( g.argc==2 || (g.argc>=3 && g.argv[2][0]=='-') ){
zCmd = "show";
nCmd = 4;
}else{
zCmd = g.argv[2];
nCmd = strlen(zCmd);
}
if( strncmp("clear-cert",zCmd,nCmd)==0 && nCmd>=4 ){
int bForce = find_option("force","f",0)!=0;
verify_all_options();
if( !bForce ){
Blob ans;
char cReply;
prompt_user(
|
| ︙ | ︙ | |||
1095 1096 1097 1098 1099 1100 1101 |
" This setting is the name of a file that contains the PEM-format\n"
" certificate and private-key used by Fossil clients to authentice\n"
" with servers. Few servers actually require this, so this setting\n"
" is usually blank.\n\n"
);
}
| < < < < < < < < < < < | 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
" This setting is the name of a file that contains the PEM-format\n"
" certificate and private-key used by Fossil clients to authentice\n"
" with servers. Few servers actually require this, so this setting\n"
" is usually blank.\n\n"
);
}
zValue = db_get("ssl-cert",0);
if( zValue ){
fossil_print("ssl-cert: (%d-byte PEM)\n", (int)strlen(zValue));
}else{
fossil_print("ssl-cert:\n");
}
if( verbose ){
|
| ︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 |
zCmd);
}
}
/*
** WEBPAGE: .well-known
**
| > | | | | | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 |
zCmd);
}
}
/*
** WEBPAGE: .well-known
**
** If the "--acme" option was supplied to "fossil server" or "fossil http" or
** similar, then this page returns the content of files found in the
** ".well-known" subdirectory of the same directory that contains the
** repository file. This facilitates Automated Certificate
** Management using tools like "certbot".
**
** The content is returned directly, without any interpretation, using
** a generic mimetype.
*/
void wellknown_page(void){
char *zPath = 0;
const char *zTail = P("name");
Blob content;
int i;
char c;
if( !g.fAllowACME ) goto wellknown_notfound;
if( g.zRepositoryName==0 ) goto wellknown_notfound;
if( zTail==0 ) goto wellknown_notfound;
zPath = mprintf("%z/.well-known/%s", file_dirname(g.zRepositoryName), zTail);
for(i=0; (c = zTail[i])!=0; i++){
if( fossil_isalnum(c) ) continue;
if( c=='.' ){
if( i==0 || zTail[i-1]=='/' || zTail[i-1]=='.' ) goto wellknown_notfound;
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 175 176 177 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ int fCgiTrace; /* True if --cgitrace is enabled */ int fQuiet; /* True if -quiet flag is present */ int fJail; /* True if running with a chroot jail */ int fHttpTrace; /* Trace outbound HTTP requests */ int fAnyTrace; /* Any kind of tracing */ char *zHttpAuth; /* HTTP Authorization user:pass information */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ const char *zHttpCmd; /* External program to do HTTP requests */ | > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ int fCgiTrace; /* True if --cgitrace is enabled */ int fQuiet; /* True if -quiet flag is present */ int fJail; /* True if running with a chroot jail */ int fHttpTrace; /* Trace outbound HTTP requests */ int fAnyTrace; /* Any kind of tracing */ int fAllowACME; /* Deliver files from .well-known */ char *zHttpAuth; /* HTTP Authorization user:pass information */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ const char *zHttpCmd; /* External program to do HTTP requests */ |
| ︙ | ︙ | |||
1698 1699 1700 1701 1702 1703 1704 |
#endif
if( c=='/' ) continue;
if( c=='_' ) continue;
if( c=='-' && zRepo[j-1]!='/' ) continue;
if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
continue;
}
| > | > | 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 |
#endif
if( c=='/' ) continue;
if( c=='_' ) continue;
if( c=='-' && zRepo[j-1]!='/' ) continue;
if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
continue;
}
if( c=='.' && g.fAllowACME && j==nBase+1
&& strncmp(&zRepo[j-1],"/.well-known/",12)==0
){
/* We allow .well-known as the top-level directory for ACME */
continue;
}
/* If we reach this point, it means that the request URI contains
** an illegal character or character combination. Provoke a
** "Not Found" error. */
szFile = 1;
|
| ︙ | ︙ | |||
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 |
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(zMimetype);
cgi_set_content(&content);
cgi_reply();
return;
}
zRepo[j] = '.';
}
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found and
** some kind of error response is required.
| > > > > > > > > > > > > > > > | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 |
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(zMimetype);
cgi_set_content(&content);
cgi_reply();
return;
}
/* In support of the ACME protocol, files under the .well-known/
** directory is always accepted.
*/
if( g.fAllowACME
&& strncmp(&zRepo[nBase],"/.well-known/",12)==0
&& file_isfile(zCleanRepo, ExtFILE)
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(mimetype_from_name(zRepo));
cgi_set_content(&content);
cgi_reply();
return;
}
zRepo[j] = '.';
}
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found and
** some kind of error response is required.
|
| ︙ | ︙ | |||
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 | ** thus also no redirecting from http: to https: will take place. ** ** If the --localauth option is given, then automatic login is performed ** for requests coming from localhost, if the "localauth" setting is not ** enabled. ** ** Options: ** --baseurl URL base URL (useful with reverse proxies) ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias N Treat URIs of the form /doc/N/... as if they were ** /doc/ckout/... ** --extroot DIR document root for the /ext extension mechanism ** --files GLOB comma-separate glob patterns for static file to serve ** --host NAME specify hostname of the server | > | 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 | ** thus also no redirecting from http: to https: will take place. ** ** If the --localauth option is given, then automatic login is performed ** for requests coming from localhost, if the "localauth" setting is not ** enabled. ** ** Options: ** --acme Deliver files from the ".well-known" subdirectory ** --baseurl URL base URL (useful with reverse proxies) ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias N Treat URIs of the form /doc/N/... as if they were ** /doc/ckout/... ** --extroot DIR document root for the /ext extension mechanism ** --files GLOB comma-separate glob patterns for static file to serve ** --host NAME specify hostname of the server |
| ︙ | ︙ | |||
2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 |
zHost = find_option("host", 0, 1);
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
decode_ssl_options();
/* We should be done with options.. */
verify_all_options();
if( g.httpUseSSL ){
if( useSCGI ){
fossil_fatal("SSL not (yet) supported for SCGI");
}
| > | 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 |
zHost = find_option("host", 0, 1);
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
decode_ssl_options();
if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1;
/* We should be done with options.. */
verify_all_options();
if( g.httpUseSSL ){
if( useSCGI ){
fossil_fatal("SSL not (yet) supported for SCGI");
}
|
| ︙ | ︙ | |||
2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 | ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. ** ** Options: ** --baseurl URL Use URL as the base (useful for reverse proxies) ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were ** /doc/ckout/... ** --create Create a new REPOSITORY if it does not already exist ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOBLIST Comma-separated list of glob patterns for static files | > | 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 | ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. ** ** Options: ** --acme Deliver files from the ".well-known" subdirectory. ** --baseurl URL Use URL as the base (useful for reverse proxies) ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were ** /doc/ckout/... ** --create Create a new REPOSITORY if it does not already exist ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOBLIST Comma-separated list of glob patterns for static files |
| ︙ | ︙ | |||
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 |
flags |= HTTP_SERVER_LOCALHOST;
}
g.zCkoutAlias = find_option("ckout-alias",0,1);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
/* Undocumented option: --debug-nofork
**
** This sets the HTTP_SERVER_NOFORK flag, which causes only the
** very first incoming TCP/IP connection to be processed. Used for
** debugging, since debugging across a fork() can be tricky
*/
| > | 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 |
flags |= HTTP_SERVER_LOCALHOST;
}
g.zCkoutAlias = find_option("ckout-alias",0,1);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1;
/* Undocumented option: --debug-nofork
**
** This sets the HTTP_SERVER_NOFORK flag, which causes only the
** very first incoming TCP/IP connection to be processed. Used for
** debugging, since debugging across a fork() can be tricky
*/
|
| ︙ | ︙ |