Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add a setup option that automatically redirects from HTTP to HTTPS on the login page, to prevent passwords from being sent in the clear over the internet. Off by default, for the sake of installations that do not support HTTPS. Also off for the "fossil ui" and "fossil server" commands. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | auto-https-redirect |
| Files: | files | file ages | folders |
| SHA1: |
b85eb7db7917938b000d6f29a5f53877 |
| User & Date: | drh 2014-11-13 16:09:33.280 |
Context
|
2014-11-19
| ||
| 13:18 | Add a configuration option that automatically redirects to SSL for HTTP connections to the login page. ... (check-in: a4e7b8629d user: drh tags: trunk) | |
|
2014-11-13
| ||
| 16:09 | Add a setup option that automatically redirects from HTTP to HTTPS on the login page, to prevent passwords from being sent in the clear over the internet. Off by default, for the sake of installations that do not support HTTPS. Also off for the "fossil ui" and "fossil server" commands. ... (Closed-Leaf check-in: b85eb7db79 user: drh tags: auto-https-redirect) | |
|
2014-11-12
| ||
| 14:37 | Fix [5a0a33f31a]: Chinese commit message File in code UTF-8 when using commit -M under WINDOWS Garbled. When the file is already detected to be valid UTF-8, don't try to do any conversion. ... (check-in: 5960016a3d user: jan.nijtmans tags: trunk) | |
Changes
Changes to src/login.c.
| ︙ | ︙ | |||
473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
char *zErrMsg = "";
int uid; /* User id logged in user */
char *zSha1Pw;
const char *zIpAddr; /* IP address of requestor */
const char *zReferer;
login_check_credentials();
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
constant_time_cmp_function, 0, 0);
zUsername = P("u");
zPasswd = P("p");
anonFlag = P("anon")!=0;
if( P("out")!=0 ){
login_clear_login_data();
| > > > > > > > > > > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
char *zErrMsg = "";
int uid; /* User id logged in user */
char *zSha1Pw;
const char *zIpAddr; /* IP address of requestor */
const char *zReferer;
login_check_credentials();
if( login_wants_https_redirect() ){
const char *zQS = P("QUERY_STRING");
if( zQS==0 ){
zQS = "";
}else if( zQS[0]!=0 ){
zQS = mprintf("?%s", zQS);
}
cgi_redirectf("%s%s%s", g.zHttpsURL, P("PATH_INFO"), zQS);
return;
}
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
constant_time_cmp_function, 0, 0);
zUsername = P("u");
zPasswd = P("p");
anonFlag = P("anon")!=0;
if( P("out")!=0 ){
login_clear_login_data();
|
| ︙ | ︙ | |||
774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
" AND length(cap)>0"
" AND length(pw)>0"
" AND constant_time_cmp(cookie,%Q)=0",
zLogin, zRemoteAddr, zCookie
);
return uid;
}
/*
** This routine examines the login cookie to see if it exists and
** is valid. If the login cookie checks out, it then sets global
** variables appropriately.
**
** g.userUid Database USER.UID value. Might be -1 for "nobody"
| > > > > > > > > > > > > > > > | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
" AND length(cap)>0"
" AND length(pw)>0"
" AND constant_time_cmp(cookie,%Q)=0",
zLogin, zRemoteAddr, zCookie
);
return uid;
}
/*
** Return true if it is appropriate to redirect login requests to HTTPS.
**
** Redirect to https is appropriate if all of the above are true:
** (1) The redirect-to-https flag is set
** (2) The current connection is http, not https or ssh
** (3) The sslNotAvailable flag is clear
*/
int login_wants_https_redirect(void){
if( g.sslNotAvailable ) return 0;
if( db_get_boolean("redirect-to-https",0)==0 ) return 0;
if( P("HTTPS")!=0 ) return 0;
return 1;
}
/*
** This routine examines the login cookie to see if it exists and
** is valid. If the login cookie checks out, it then sets global
** variables appropriately.
**
** g.userUid Database USER.UID value. Might be -1 for "nobody"
|
| ︙ | ︙ | |||
810 811 812 813 814 815 816 |
** then there is no need to check user credentials.
**
** This feature allows the "fossil ui" command to give the user
** full access rights without having to log in.
*/
zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
| | | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
** then there is no need to check user credentials.
**
** This feature allows the "fossil ui" command to give the user
** full access rights without having to log in.
*/
zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
(g.fSshClient & CGI_SSH_CLIENT)!=0 )
&& g.useLocalauth
&& db_get_int("localauth",0)==0
&& P("HTTPS")==0
){
if( g.localOpen ) zLogin = db_lget("default-user",0);
if( zLogin!=0 ){
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zLogin);
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 157 158 159 160 161 | int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ char *zSshCmd; /* SSH command string */ int fNoSync; /* Do not do an autosync ever. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ char *zErrMsg; /* Text of an error message */ int sslNotAvailable; /* SSL is not available. Do not redirect to https: */ Blob cgiIn; /* Input to an xfer www method */ int cgiOutput; /* Write error and status messages to CGI */ | > | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ char *zSshCmd; /* SSH command string */ int fNoSync; /* Do not do an autosync ever. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zHttpsURL; /* zBaseURL translated to https: */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ char *zErrMsg; /* Text of an error message */ int sslNotAvailable; /* SSL is not available. Do not redirect to https: */ Blob cgiIn; /* Input to an xfer www method */ int cgiOutput; /* Write error and status messages to CGI */ |
| ︙ | ︙ | |||
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 |
zMode = PD("HTTPS","off");
zCur = PD("SCRIPT_NAME","/");
i = strlen(zCur);
while( i>0 && zCur[i-1]=='/' ) i--;
if( fossil_stricmp(zMode,"on")==0 ){
g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
g.zTop = &g.zBaseURL[8+strlen(zHost)];
}else{
g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
g.zTop = &g.zBaseURL[7+strlen(zHost)];
}
}
if( db_is_writeable("repository") ){
if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
db_multi_exec("INSERT INTO config(name,value,mtime)"
"VALUES('baseurl:%q',1,now())", g.zBaseURL);
}else{
| > > | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 |
zMode = PD("HTTPS","off");
zCur = PD("SCRIPT_NAME","/");
i = strlen(zCur);
while( i>0 && zCur[i-1]=='/' ) i--;
if( fossil_stricmp(zMode,"on")==0 ){
g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
g.zTop = &g.zBaseURL[8+strlen(zHost)];
g.zHttpsURL = g.zBaseURL;
}else{
g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
g.zTop = &g.zBaseURL[7+strlen(zHost)];
g.zHttpsURL = mprintf("https://%s%.*s", zHost, i, zCur);
}
}
if( db_is_writeable("repository") ){
if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
db_multi_exec("INSERT INTO config(name,value,mtime)"
"VALUES('baseurl:%q',1,now())", g.zBaseURL);
}else{
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
64 65 66 67 68 69 70 |
style_header("Server Administration");
/* Make sure the header contains <base href="...">. Issue a warning
** if it does not. */
if( !cgi_header_contains("<base href=") ){
@ <p class="generalError"><b>Configuration Error:</b> Please add
| | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
style_header("Server Administration");
/* Make sure the header contains <base href="...">. Issue a warning
** if it does not. */
if( !cgi_header_contains("<base href=") ){
@ <p class="generalError"><b>Configuration Error:</b> Please add
@ <tt><base href="$secureurl/$current_page"></tt> after
@ <tt><head></tt> in the <a href="setup_header">HTML header</a>!</p>
}
@ <table border="0" cellspacing="7">
setup_menu_entry("Users", "setup_ulist",
"Grant privileges to individual users.");
setup_menu_entry("Access", "setup_access",
|
| ︙ | ︙ | |||
971 972 973 974 975 976 977 978 979 980 981 982 983 984 |
}
style_header("Access Control Settings");
db_begin_transaction();
@ <form action="%s(g.zTop)/setup_access" method="post"><div>
login_insert_csrf_secret();
@ <hr />
onoff_attribute("Require password for local access",
"localauth", "localauth", 0, 0);
@ <p>When enabled, the password sign-in is always required for
@ web access. When disabled, unrestricted web access from 127.0.0.1
@ is allowed for the <a href="%s(g.zTop)/help/ui">fossil ui</a> command or
@ from the <a href="%s(g.zTop)/help/server">fossil server</a>,
@ <a href="%s(g.zTop)/help/http">fossil http</a> commands when the
| > > > > > > > > | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 |
}
style_header("Access Control Settings");
db_begin_transaction();
@ <form action="%s(g.zTop)/setup_access" method="post"><div>
login_insert_csrf_secret();
@ <hr />
onoff_attribute("Redirect to HTTPS on the Login page",
"redirect-to-https", "redirhttps", 0, 0);
@ <p>When selected, force the use of HTTPS for the Login page.
@ <p>Details: When enabled, this option causes the $secureurl TH1
@ variable is set to an "https:" variant of $baseurl. Otherwise,
@ $secureurl is just an alias for $baseurl. Also when enabled, the
@ Login page redirects to https if accessed via http.
@ <hr />
onoff_attribute("Require password for local access",
"localauth", "localauth", 0, 0);
@ <p>When enabled, the password sign-in is always required for
@ web access. When disabled, unrestricted web access from 127.0.0.1
@ is allowed for the <a href="%s(g.zTop)/help/ui">fossil ui</a> command or
@ from the <a href="%s(g.zTop)/help/server">fossil server</a>,
@ <a href="%s(g.zTop)/help/http">fossil http</a> commands when the
|
| ︙ | ︙ | |||
1549 1550 1551 1552 1553 1554 1555 |
}else if( P("fixbase")!=0 ){
const char *z = db_get("header", (char*)zDefaultHeader);
char *zHead = strstr(z, "<head>");
if( strstr(z, "<base href=")==0 && zHead!=0 ){
char *zNew;
char *zTail = &zHead[6];
while( fossil_isspace(zTail[0]) ) zTail++;
| | | | 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 |
}else if( P("fixbase")!=0 ){
const char *z = db_get("header", (char*)zDefaultHeader);
char *zHead = strstr(z, "<head>");
if( strstr(z, "<base href=")==0 && zHead!=0 ){
char *zNew;
char *zTail = &zHead[6];
while( fossil_isspace(zTail[0]) ) zTail++;
zNew = mprintf("%.*s\n<base href=\"$secureurl/$current_page\" />\n%s",
zHead+6-z, z, zTail);
cgi_replace_parameter("header", zNew);
db_set("header", zNew, 0);
}
}
style_header("Edit Page Header");
@ <form action="%R/setup_header" method="post"><div>
/* Make sure the header contains <base href="...">. Issue a warning
** if it does not. */
if( !cgi_header_contains("<base href=") ){
@ <p class="generalError">Please add
@ <tt><base href="$secureurl/$current_page"></tt> after
@ <tt><head></tt> in the header!
@ <input type="submit" name="fixbase" value="Add <base> Now"></p>
}
login_insert_csrf_secret();
@ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
@ generate the beginning of every page through start of the main
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
/* Generate the header up through the main menu */
Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
Th_Store("title", zTitle);
Th_Store("baseurl", g.zBaseURL);
Th_Store("home", g.zTop);
Th_Store("index_page", db_get("index-page","/home"));
if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
Th_Store("current_page", local_zCurrentPage);
Th_Store("csrf_token", g.zCsrfToken);
Th_Store("release_version", RELEASE_VERSION);
Th_Store("manifest_version", MANIFEST_VERSION);
| > > > > > | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
/* Generate the header up through the main menu */
Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
Th_Store("title", zTitle);
Th_Store("baseurl", g.zBaseURL);
if( login_wants_https_redirect() ){
Th_Store("secureurl", g.zHttpsURL);
}else{
Th_Store("secureurl", g.zBaseURL);
}
Th_Store("home", g.zTop);
Th_Store("index_page", db_get("index-page","/home"));
if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
Th_Store("current_page", local_zCurrentPage);
Th_Store("csrf_token", g.zCsrfToken);
Th_Store("release_version", RELEASE_VERSION);
Th_Store("manifest_version", MANIFEST_VERSION);
|
| ︙ | ︙ | |||
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 |
}
}
/* Process through TH1 in order to give an opportunity to substitute
** variables such as $baseurl.
*/
Th_Store("baseurl", g.zBaseURL);
Th_Store("home", g.zTop);
image_url_var("logo");
image_url_var("background");
Th_Render(blob_str(&css));
/* Tell CGI that the content returned by this page is considered cacheable */
g.isConst = 1;
| > | 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
}
}
/* Process through TH1 in order to give an opportunity to substitute
** variables such as $baseurl.
*/
Th_Store("baseurl", g.zBaseURL);
Th_Store("httpsurl", g.zHttpsURL);
Th_Store("home", g.zTop);
image_url_var("logo");
image_url_var("background");
Th_Render(blob_str(&css));
/* Tell CGI that the content returned by this page is considered cacheable */
g.isConst = 1;
|
| ︙ | ︙ | |||
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 |
style_submenu_element("Hide Cookies", "Hide Cookies",
"%s/test_env", g.zTop);
}
#if !defined(_WIN32)
@ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
@ g.zBaseURL = %h(g.zBaseURL)<br />
@ g.zTop = %h(g.zTop)<br />
for(i=0, c='a'; c<='z'; c++){
if( login_has_capability(&c, 1) ) zCap[i++] = c;
}
zCap[i] = 0;
@ g.userUid = %d(g.userUid)<br />
@ g.zLogin = %h(g.zLogin)<br />
| > | 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 |
style_submenu_element("Hide Cookies", "Hide Cookies",
"%s/test_env", g.zTop);
}
#if !defined(_WIN32)
@ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
@ g.zBaseURL = %h(g.zBaseURL)<br />
@ g.zHttpsURL = %h(g.zHttpsURL)<br />
@ g.zTop = %h(g.zTop)<br />
for(i=0, c='a'; c<='z'; c++){
if( login_has_capability(&c, 1) ) zCap[i++] = c;
}
zCap[i] = 0;
@ g.userUid = %d(g.userUid)<br />
@ g.zLogin = %h(g.zLogin)<br />
|
| ︙ | ︙ |