Fossil SCM

Add the capability for Fossil to directly interpret the Authentication: HTTP header for Basic Authentication, if enabled on the /setup_access page. Disabled by default.

drh 2017-03-13 23:47 trunk merge
Commit 315cf243685004578a3924f93631222f7dd39b6b82caa7aaef86d6c86f8a2bdc
+2
--- src/cgi.c
+++ src/cgi.c
@@ -1444,10 +1444,12 @@
14441444
cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
14451445
}else if( fossil_strcmp(zFieldName,"referer:")==0 ){
14461446
cgi_setenv("HTTP_REFERER", zVal);
14471447
}else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
14481448
cgi_setenv("HTTP_USER_AGENT", zVal);
1449
+ }else if( fossil_strcmp(zFieldName,"authorization:")==0 ){
1450
+ cgi_setenv("HTTP_AUTHORIZATION", zVal);
14491451
}else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
14501452
const char *zIpAddr = cgi_accept_forwarded_for(zVal);
14511453
if( zIpAddr!=0 ){
14521454
g.zIpAddr = mprintf("%s", zIpAddr);
14531455
cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
14541456
--- src/cgi.c
+++ src/cgi.c
@@ -1444,10 +1444,12 @@
1444 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1445 }else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1446 cgi_setenv("HTTP_REFERER", zVal);
1447 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1448 cgi_setenv("HTTP_USER_AGENT", zVal);
 
 
1449 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1450 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1451 if( zIpAddr!=0 ){
1452 g.zIpAddr = mprintf("%s", zIpAddr);
1453 cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
1454
--- src/cgi.c
+++ src/cgi.c
@@ -1444,10 +1444,12 @@
1444 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1445 }else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1446 cgi_setenv("HTTP_REFERER", zVal);
1447 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1448 cgi_setenv("HTTP_USER_AGENT", zVal);
1449 }else if( fossil_strcmp(zFieldName,"authorization:")==0 ){
1450 cgi_setenv("HTTP_AUTHORIZATION", zVal);
1451 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1452 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1453 if( zIpAddr!=0 ){
1454 g.zIpAddr = mprintf("%s", zIpAddr);
1455 cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
1456
+59
--- src/login.c
+++ src/login.c
@@ -966,10 +966,69 @@
966966
if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
967967
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
968968
" AND length(cap)>0 AND length(pw)>0", zRemoteUser);
969969
}
970970
}
971
+
972
+ /* If the request didn't provide a login cookie or the login cookie didn't
973
+ ** match a known valid user, check the HTTP "Authorization" header and
974
+ ** see if those credentials are valid for a known user.
975
+ */
976
+ if( uid==0 ){
977
+ const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0);
978
+
979
+ /* Check to see if the HTTP "Authorization" header is present
980
+ */
981
+ if( zHTTPAuth!=0 && zHTTPAuth[0]!=0
982
+ && db_get_boolean("http_authentication_ok",0)
983
+ ){
984
+ char *zBuf = fossil_strdup(zHTTPAuth);
985
+
986
+ if( zBuf!=0 ){
987
+ char *zPos;
988
+ char *zTok = strtok_r(zBuf, " ", &zPos);
989
+
990
+ if( zTok != 0 ){
991
+ /* Check to see if the authorization scheme is HTTP
992
+ ** basic auth.
993
+ */
994
+ if (strncmp(zTok, "Basic", zTok - zBuf) == 0) {
995
+ zTok = strtok_r(NULL, " ", &zPos);
996
+ int zBytesDecoded = 0;
997
+ char *zDecodedAuth = decode64(zTok, &zBytesDecoded);
998
+
999
+ char *zUsername = strtok_r(zDecodedAuth, ":", &zPos);
1000
+ char *zPasswd = strtok_r(NULL, ":", &zPos);
1001
+
1002
+ if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
1003
+ /* Attempting to log in as the user provided by HTTP
1004
+ ** basic auth
1005
+ */
1006
+ uid = login_search_uid(zUsername, zPasswd);
1007
+ if( uid>0 ){
1008
+ record_login_attempt(zUsername, zIpAddr, 1);
1009
+ }else{
1010
+ record_login_attempt(zUsername, zIpAddr, 0);
1011
+
1012
+ /* The user attempted to login specifically with HTTP basic
1013
+ ** auth, but provided invalid credentials. Inform them of
1014
+ ** the failed login attempt via 401.
1015
+ */
1016
+ cgi_set_status(401, "Unauthorized");
1017
+ cgi_reply();
1018
+ fossil_exit(0);
1019
+ }
1020
+ }
1021
+
1022
+ fossil_free(zDecodedAuth);
1023
+ }
1024
+ }
1025
+
1026
+ fossil_free(zBuf);
1027
+ }
1028
+ }
1029
+ }
9711030
9721031
/* If no user found yet, try to log in as "nobody" */
9731032
if( uid==0 ){
9741033
uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
9751034
if( uid==0 ){
9761035
--- src/login.c
+++ src/login.c
@@ -966,10 +966,69 @@
966 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
967 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
968 " AND length(cap)>0 AND length(pw)>0", zRemoteUser);
969 }
970 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
971
972 /* If no user found yet, try to log in as "nobody" */
973 if( uid==0 ){
974 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
975 if( uid==0 ){
976
--- src/login.c
+++ src/login.c
@@ -966,10 +966,69 @@
966 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
967 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
968 " AND length(cap)>0 AND length(pw)>0", zRemoteUser);
969 }
970 }
971
972 /* If the request didn't provide a login cookie or the login cookie didn't
973 ** match a known valid user, check the HTTP "Authorization" header and
974 ** see if those credentials are valid for a known user.
975 */
976 if( uid==0 ){
977 const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0);
978
979 /* Check to see if the HTTP "Authorization" header is present
980 */
981 if( zHTTPAuth!=0 && zHTTPAuth[0]!=0
982 && db_get_boolean("http_authentication_ok",0)
983 ){
984 char *zBuf = fossil_strdup(zHTTPAuth);
985
986 if( zBuf!=0 ){
987 char *zPos;
988 char *zTok = strtok_r(zBuf, " ", &zPos);
989
990 if( zTok != 0 ){
991 /* Check to see if the authorization scheme is HTTP
992 ** basic auth.
993 */
994 if (strncmp(zTok, "Basic", zTok - zBuf) == 0) {
995 zTok = strtok_r(NULL, " ", &zPos);
996 int zBytesDecoded = 0;
997 char *zDecodedAuth = decode64(zTok, &zBytesDecoded);
998
999 char *zUsername = strtok_r(zDecodedAuth, ":", &zPos);
1000 char *zPasswd = strtok_r(NULL, ":", &zPos);
1001
1002 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
1003 /* Attempting to log in as the user provided by HTTP
1004 ** basic auth
1005 */
1006 uid = login_search_uid(zUsername, zPasswd);
1007 if( uid>0 ){
1008 record_login_attempt(zUsername, zIpAddr, 1);
1009 }else{
1010 record_login_attempt(zUsername, zIpAddr, 0);
1011
1012 /* The user attempted to login specifically with HTTP basic
1013 ** auth, but provided invalid credentials. Inform them of
1014 ** the failed login attempt via 401.
1015 */
1016 cgi_set_status(401, "Unauthorized");
1017 cgi_reply();
1018 fossil_exit(0);
1019 }
1020 }
1021
1022 fossil_free(zDecodedAuth);
1023 }
1024 }
1025
1026 fossil_free(zBuf);
1027 }
1028 }
1029 }
1030
1031 /* If no user found yet, try to log in as "nobody" */
1032 if( uid==0 ){
1033 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
1034 if( uid==0 ){
1035
--- src/setup.c
+++ src/setup.c
@@ -1108,10 +1108,18 @@
11081108
"remote_user_ok", "remote_user_ok", 0, 0);
11091109
@ <p>When enabled, if the REMOTE_USER environment variable is set to the
11101110
@ login name of a valid user and no other login credentials are available,
11111111
@ then the REMOTE_USER is accepted as an authenticated user.
11121112
@ </p>
1113
+ @
1114
+ @ <hr />
1115
+ onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
1116
+ "http_authentication_ok", "http_authentication_ok", 0, 0);
1117
+ @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
1118
+ @ variable or the "Authentication:" HTTP header to find the username and
1119
+ @ password. This is another way of supporting Basic Authenitication.
1120
+ @ </p>
11131121
@
11141122
@ <hr />
11151123
entry_attribute("IP address terms used in login cookie", 3,
11161124
"ip-prefix-terms", "ipt", "2", 0);
11171125
@ <p>The number of octets of of the IP address used in the login cookie.
11181126
--- src/setup.c
+++ src/setup.c
@@ -1108,10 +1108,18 @@
1108 "remote_user_ok", "remote_user_ok", 0, 0);
1109 @ <p>When enabled, if the REMOTE_USER environment variable is set to the
1110 @ login name of a valid user and no other login credentials are available,
1111 @ then the REMOTE_USER is accepted as an authenticated user.
1112 @ </p>
 
 
 
 
 
 
 
 
1113 @
1114 @ <hr />
1115 entry_attribute("IP address terms used in login cookie", 3,
1116 "ip-prefix-terms", "ipt", "2", 0);
1117 @ <p>The number of octets of of the IP address used in the login cookie.
1118
--- src/setup.c
+++ src/setup.c
@@ -1108,10 +1108,18 @@
1108 "remote_user_ok", "remote_user_ok", 0, 0);
1109 @ <p>When enabled, if the REMOTE_USER environment variable is set to the
1110 @ login name of a valid user and no other login credentials are available,
1111 @ then the REMOTE_USER is accepted as an authenticated user.
1112 @ </p>
1113 @
1114 @ <hr />
1115 onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
1116 "http_authentication_ok", "http_authentication_ok", 0, 0);
1117 @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
1118 @ variable or the "Authentication:" HTTP header to find the username and
1119 @ password. This is another way of supporting Basic Authenitication.
1120 @ </p>
1121 @
1122 @ <hr />
1123 entry_attribute("IP address terms used in login cookie", 3,
1124 "ip-prefix-terms", "ipt", "2", 0);
1125 @ <p>The number of octets of of the IP address used in the login cookie.
1126

Keyboard Shortcuts

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