Fossil SCM

Simplify the Basic Authentication implementation, removing the need for the strtok_r() library function.

drh 2017-03-15 00:19 trunk
Commit 2e76b99f5ce5301c4cf82f06d069ec608da888cce543cf8d736d51b110eff6d2
1 file changed +54 -91
+54 -91
--- src/login.c
+++ src/login.c
@@ -49,48 +49,10 @@
4949
# define sleep Sleep /* windows does not have sleep, but Sleep */
5050
# endif
5151
#endif
5252
#include <time.h>
5353
54
-#ifdef _WIN32
55
-/*
56
-** MinGW doesn't have strtok_r in its libc. Here's a public domain one
57
-** found at StackOverflow as a work-around, with formatting adjusted to
58
-** make it more like the usual style here. This is certainly the wrong
59
-** place for it, which is emphasized by making the function static.
60
-**
61
-** See http://stackoverflow.com/a/12979321/68204
62
-**
63
-** public domain strtok_r() by Charlie Gordon
64
-** from comp.lang.c 9/14/2007
65
-** http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684
66
-** (Declaration that it's public domain):
67
-** http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c
68
-*/
69
-static char* win32_strtok_r(
70
- char *str,
71
- const char *delim,
72
- char **nextp
73
-){
74
- char *ret;
75
- if( str == NULL ){
76
- str = *nextp;
77
- }
78
- str += strspn(str, delim);
79
- if( *str == '\0' ){
80
- return NULL;
81
- }
82
- ret = str;
83
- str += strcspn(str, delim);
84
- if( *str ){
85
- *str++ = '\0';
86
- }
87
- *nextp = str;
88
- return ret;
89
-}
90
-#define strtok_r win32_strtok_r
91
-#endif
9254
9355
/*
9456
** Return the login-group name. Or return 0 if this repository is
9557
** not a member of a login-group.
9658
*/
@@ -885,10 +847,62 @@
885847
if( db_get_boolean("redirect-to-https",0)==0 ) return 0;
886848
if( P("HTTPS")!=0 ) return 0;
887849
return 1;
888850
}
889851
852
+
853
+/*
854
+** Attempt to use Basic Authentication to establish the user. Return the
855
+** (non-zero) uid if successful. Return 0 if it does not work.
856
+*/
857
+static logic_basic_authentication(const char *zIpAddr){
858
+ const char *zAuth = PD("HTTP_AUTHORIZATION", 0);
859
+ int i;
860
+ int uid = 0;
861
+ int nDecode = 0;
862
+ char *zDecode = 0;
863
+ const char *zUsername = 0;
864
+ const char *zPasswd = 0;
865
+
866
+
867
+ if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
868
+ while( fossil_isspace(zAuth[0]) ) zAuth++; /* Skip leading whitespace */
869
+ if( strncmp(zAuth, "Basic ", 6)!=0 ) return 0; /* Fail: Not Basic Authentication */
870
+
871
+ /* Parse out the username and password, separated by a ":" */
872
+ zAuth += 6;
873
+ while( fossil_isspace(zAuth[0]) ) zAuth++;
874
+ zDecode = decode64(zAuth, &nDecode);
875
+
876
+ for(i=0; zDecode[i] && zDecode[i]!=':'; i++){}
877
+ if( zDecode[i] ){
878
+ zDecode[i] = 0;
879
+ zUsername = zDecode;
880
+ zPasswd = &zDecode[i+1];
881
+
882
+ /* Attempting to log in as the user provided by HTTP
883
+ ** basic auth
884
+ */
885
+ uid = login_search_uid(zUsername, zPasswd);
886
+ if( uid>0 ){
887
+ record_login_attempt(zUsername, zIpAddr, 1);
888
+ }else{
889
+ record_login_attempt(zUsername, zIpAddr, 0);
890
+
891
+ /* The user attempted to login specifically with HTTP basic
892
+ ** auth, but provided invalid credentials. Inform them of
893
+ ** the failed login attempt via 401.
894
+ */
895
+ cgi_set_status(401, "Unauthorized");
896
+ cgi_reply();
897
+ fossil_exit(0);
898
+ }
899
+ }
900
+ fossil_free(zDecode);
901
+ return uid;
902
+}
903
+
890904
/*
891905
** This routine examines the login cookie to see if it exists and
892906
** is valid. If the login cookie checks out, it then sets global
893907
** variables appropriately.
894908
**
@@ -1010,63 +1024,12 @@
10101024
10111025
/* If the request didn't provide a login cookie or the login cookie didn't
10121026
** match a known valid user, check the HTTP "Authorization" header and
10131027
** see if those credentials are valid for a known user.
10141028
*/
1015
- if( uid==0 ){
1016
- const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0);
1017
-
1018
- /* Check to see if the HTTP "Authorization" header is present
1019
- */
1020
- if( zHTTPAuth!=0 && zHTTPAuth[0]!=0
1021
- && db_get_boolean("http_authentication_ok",0)
1022
- ){
1023
- char *zBuf = fossil_strdup(zHTTPAuth);
1024
-
1025
- if( zBuf!=0 ){
1026
- char *zPos;
1027
- char *zTok = strtok_r(zBuf, " ", &zPos);
1028
-
1029
- if( zTok != 0 ){
1030
- /* Check to see if the authorization scheme is HTTP
1031
- ** basic auth.
1032
- */
1033
- if (strncmp(zTok, "Basic", zTok - zBuf) == 0) {
1034
- zTok = strtok_r(NULL, " ", &zPos);
1035
- int zBytesDecoded = 0;
1036
- char *zDecodedAuth = decode64(zTok, &zBytesDecoded);
1037
-
1038
- char *zUsername = strtok_r(zDecodedAuth, ":", &zPos);
1039
- char *zPasswd = strtok_r(NULL, ":", &zPos);
1040
-
1041
- if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
1042
- /* Attempting to log in as the user provided by HTTP
1043
- ** basic auth
1044
- */
1045
- uid = login_search_uid(zUsername, zPasswd);
1046
- if( uid>0 ){
1047
- record_login_attempt(zUsername, zIpAddr, 1);
1048
- }else{
1049
- record_login_attempt(zUsername, zIpAddr, 0);
1050
-
1051
- /* The user attempted to login specifically with HTTP basic
1052
- ** auth, but provided invalid credentials. Inform them of
1053
- ** the failed login attempt via 401.
1054
- */
1055
- cgi_set_status(401, "Unauthorized");
1056
- cgi_reply();
1057
- fossil_exit(0);
1058
- }
1059
- }
1060
-
1061
- fossil_free(zDecodedAuth);
1062
- }
1063
- }
1064
-
1065
- fossil_free(zBuf);
1066
- }
1067
- }
1029
+ if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1030
+ uid = logic_basic_authentication(zIpAddr);
10681031
}
10691032
10701033
/* If no user found yet, try to log in as "nobody" */
10711034
if( uid==0 ){
10721035
uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
10731036
--- src/login.c
+++ src/login.c
@@ -49,48 +49,10 @@
49 # define sleep Sleep /* windows does not have sleep, but Sleep */
50 # endif
51 #endif
52 #include <time.h>
53
54 #ifdef _WIN32
55 /*
56 ** MinGW doesn't have strtok_r in its libc. Here's a public domain one
57 ** found at StackOverflow as a work-around, with formatting adjusted to
58 ** make it more like the usual style here. This is certainly the wrong
59 ** place for it, which is emphasized by making the function static.
60 **
61 ** See http://stackoverflow.com/a/12979321/68204
62 **
63 ** public domain strtok_r() by Charlie Gordon
64 ** from comp.lang.c 9/14/2007
65 ** http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684
66 ** (Declaration that it's public domain):
67 ** http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c
68 */
69 static char* win32_strtok_r(
70 char *str,
71 const char *delim,
72 char **nextp
73 ){
74 char *ret;
75 if( str == NULL ){
76 str = *nextp;
77 }
78 str += strspn(str, delim);
79 if( *str == '\0' ){
80 return NULL;
81 }
82 ret = str;
83 str += strcspn(str, delim);
84 if( *str ){
85 *str++ = '\0';
86 }
87 *nextp = str;
88 return ret;
89 }
90 #define strtok_r win32_strtok_r
91 #endif
92
93 /*
94 ** Return the login-group name. Or return 0 if this repository is
95 ** not a member of a login-group.
96 */
@@ -885,10 +847,62 @@
885 if( db_get_boolean("redirect-to-https",0)==0 ) return 0;
886 if( P("HTTPS")!=0 ) return 0;
887 return 1;
888 }
889
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
890 /*
891 ** This routine examines the login cookie to see if it exists and
892 ** is valid. If the login cookie checks out, it then sets global
893 ** variables appropriately.
894 **
@@ -1010,63 +1024,12 @@
1010
1011 /* If the request didn't provide a login cookie or the login cookie didn't
1012 ** match a known valid user, check the HTTP "Authorization" header and
1013 ** see if those credentials are valid for a known user.
1014 */
1015 if( uid==0 ){
1016 const char *zHTTPAuth = PD("HTTP_AUTHORIZATION", 0);
1017
1018 /* Check to see if the HTTP "Authorization" header is present
1019 */
1020 if( zHTTPAuth!=0 && zHTTPAuth[0]!=0
1021 && db_get_boolean("http_authentication_ok",0)
1022 ){
1023 char *zBuf = fossil_strdup(zHTTPAuth);
1024
1025 if( zBuf!=0 ){
1026 char *zPos;
1027 char *zTok = strtok_r(zBuf, " ", &zPos);
1028
1029 if( zTok != 0 ){
1030 /* Check to see if the authorization scheme is HTTP
1031 ** basic auth.
1032 */
1033 if (strncmp(zTok, "Basic", zTok - zBuf) == 0) {
1034 zTok = strtok_r(NULL, " ", &zPos);
1035 int zBytesDecoded = 0;
1036 char *zDecodedAuth = decode64(zTok, &zBytesDecoded);
1037
1038 char *zUsername = strtok_r(zDecodedAuth, ":", &zPos);
1039 char *zPasswd = strtok_r(NULL, ":", &zPos);
1040
1041 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
1042 /* Attempting to log in as the user provided by HTTP
1043 ** basic auth
1044 */
1045 uid = login_search_uid(zUsername, zPasswd);
1046 if( uid>0 ){
1047 record_login_attempt(zUsername, zIpAddr, 1);
1048 }else{
1049 record_login_attempt(zUsername, zIpAddr, 0);
1050
1051 /* The user attempted to login specifically with HTTP basic
1052 ** auth, but provided invalid credentials. Inform them of
1053 ** the failed login attempt via 401.
1054 */
1055 cgi_set_status(401, "Unauthorized");
1056 cgi_reply();
1057 fossil_exit(0);
1058 }
1059 }
1060
1061 fossil_free(zDecodedAuth);
1062 }
1063 }
1064
1065 fossil_free(zBuf);
1066 }
1067 }
1068 }
1069
1070 /* If no user found yet, try to log in as "nobody" */
1071 if( uid==0 ){
1072 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
1073
--- src/login.c
+++ src/login.c
@@ -49,48 +49,10 @@
49 # define sleep Sleep /* windows does not have sleep, but Sleep */
50 # endif
51 #endif
52 #include <time.h>
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
55 /*
56 ** Return the login-group name. Or return 0 if this repository is
57 ** not a member of a login-group.
58 */
@@ -885,10 +847,62 @@
847 if( db_get_boolean("redirect-to-https",0)==0 ) return 0;
848 if( P("HTTPS")!=0 ) return 0;
849 return 1;
850 }
851
852
853 /*
854 ** Attempt to use Basic Authentication to establish the user. Return the
855 ** (non-zero) uid if successful. Return 0 if it does not work.
856 */
857 static logic_basic_authentication(const char *zIpAddr){
858 const char *zAuth = PD("HTTP_AUTHORIZATION", 0);
859 int i;
860 int uid = 0;
861 int nDecode = 0;
862 char *zDecode = 0;
863 const char *zUsername = 0;
864 const char *zPasswd = 0;
865
866
867 if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
868 while( fossil_isspace(zAuth[0]) ) zAuth++; /* Skip leading whitespace */
869 if( strncmp(zAuth, "Basic ", 6)!=0 ) return 0; /* Fail: Not Basic Authentication */
870
871 /* Parse out the username and password, separated by a ":" */
872 zAuth += 6;
873 while( fossil_isspace(zAuth[0]) ) zAuth++;
874 zDecode = decode64(zAuth, &nDecode);
875
876 for(i=0; zDecode[i] && zDecode[i]!=':'; i++){}
877 if( zDecode[i] ){
878 zDecode[i] = 0;
879 zUsername = zDecode;
880 zPasswd = &zDecode[i+1];
881
882 /* Attempting to log in as the user provided by HTTP
883 ** basic auth
884 */
885 uid = login_search_uid(zUsername, zPasswd);
886 if( uid>0 ){
887 record_login_attempt(zUsername, zIpAddr, 1);
888 }else{
889 record_login_attempt(zUsername, zIpAddr, 0);
890
891 /* The user attempted to login specifically with HTTP basic
892 ** auth, but provided invalid credentials. Inform them of
893 ** the failed login attempt via 401.
894 */
895 cgi_set_status(401, "Unauthorized");
896 cgi_reply();
897 fossil_exit(0);
898 }
899 }
900 fossil_free(zDecode);
901 return uid;
902 }
903
904 /*
905 ** This routine examines the login cookie to see if it exists and
906 ** is valid. If the login cookie checks out, it then sets global
907 ** variables appropriately.
908 **
@@ -1010,63 +1024,12 @@
1024
1025 /* If the request didn't provide a login cookie or the login cookie didn't
1026 ** match a known valid user, check the HTTP "Authorization" header and
1027 ** see if those credentials are valid for a known user.
1028 */
1029 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1030 uid = logic_basic_authentication(zIpAddr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1031 }
1032
1033 /* If no user found yet, try to log in as "nobody" */
1034 if( uid==0 ){
1035 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
1036

Keyboard Shortcuts

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