From 8d5dfd4b06d882f716f81ddae5f7e936a0fca2cc Mon Sep 17 00:00:00 2001 From: stefanocasazza Date: Tue, 17 Jul 2018 14:12:26 +0200 Subject: [PATCH] auth fix --- include/ulib/file.h | 53 +++++++++++------ include/ulib/string.h | 5 +- include/ulib/utility/uhttp.h | 2 + src/ulib/string.cpp | 18 ++++-- src/ulib/utility/uhttp.cpp | 110 ++++++++++++++++++++++++++++++++--- tests/examples/TSA/tsaserial | 2 +- tests/ulib/test_json.cpp | 10 ++++ 7 files changed, 169 insertions(+), 31 deletions(-) diff --git a/include/ulib/file.h b/include/ulib/file.h index 6b30055d..ddf3591d 100644 --- a/include/ulib/file.h +++ b/include/ulib/file.h @@ -627,23 +627,6 @@ public: U_RETURN(st_dev != parent_id); } - // MODIFIER - - bool modified() - { - U_TRACE_NO_PARAM(0, "UFile::modified()") - - time_t mtime = st_mtime; - - fstat(); - - U_INTERNAL_DUMP("mtime = %ld, st_mtime = %ld", (long)mtime, (long)st_mtime) - - if (mtime != st_mtime) U_RETURN(true); - - U_RETURN(false); - } - static bool isBlocking(int _fd, int& flags) // actual state is blocking...? { U_TRACE(1, "UFile::isBlocking(%d,%d)", _fd, flags) @@ -754,6 +737,42 @@ public: U_RETURN(false); } + bool isModified() + { + U_TRACE_NO_PARAM(0, "UFile::isModified()") + + time_t old = st_mtime; + + fstat(); + + U_INTERNAL_DUMP("old = %#3D, st_mtime = %#3D", old, st_mtime) + + if (st_mtime > old) U_RETURN(true); + + U_RETURN(false); + } + + static bool isModified(const char* _pathname, time_t& old) + { + U_TRACE(0, "UFile::isModified(%S,%ld)", _pathname, old) + + struct stat st; + + if (U_SYSCALL(stat, "%S,%p", U_PATH_CONV(_pathname), &st) == 0) + { + U_INTERNAL_DUMP("old = %#3D, st.st_mtime = %#3D", old, st.st_mtime) + + if (st.st_mtime > old) + { + old = st.st_mtime; + + U_RETURN(true); + } + } + + U_RETURN(false); + } + static bool isRunningInChroot(); static bool fallocate(int fd, uint32_t n); static bool chdir(const char* path, bool flag_save = false); diff --git a/include/ulib/string.h b/include/ulib/string.h index 456d9c2f..344aa7fa 100644 --- a/include/ulib/string.h +++ b/include/ulib/string.h @@ -36,7 +36,7 @@ enum StringAllocationIndex { STR_ALLOCATE_INDEX_SSI = STR_ALLOCATE_INDEX_IMAP+4, STR_ALLOCATE_INDEX_NOCAT = STR_ALLOCATE_INDEX_SSI+2, STR_ALLOCATE_INDEX_HTTP = STR_ALLOCATE_INDEX_NOCAT+2, - STR_ALLOCATE_INDEX_QUERY_PARSER = STR_ALLOCATE_INDEX_HTTP+9, + STR_ALLOCATE_INDEX_QUERY_PARSER = STR_ALLOCATE_INDEX_HTTP+11, STR_ALLOCATE_INDEX_ORM = STR_ALLOCATE_INDEX_QUERY_PARSER+5, STR_ALLOCATE_INDEX_HTTP2 = STR_ALLOCATE_INDEX_ORM+15 }; @@ -416,6 +416,7 @@ public: U_RETURN(false); } + bool equal(const char* s) const { return equal(s, u__strlen(s, __PRETTY_FUNCTION__)); } bool equal(const UStringRep* rep) const { return equal(rep->str, rep->_length); } // Equal with ignore case @@ -1155,6 +1156,8 @@ public: static const UString* str_storage_keyid; static const UString* str_websocket_key; static const UString* str_websocket_prot; + static const UString* str_htdigest; + static const UString* str_htpasswd; // QUERY PARSER static const UString* str_p1; static const UString* str_p2; diff --git a/include/ulib/utility/uhttp.h b/include/ulib/utility/uhttp.h index a43fa9d0..a9403186 100644 --- a/include/ulib/utility/uhttp.h +++ b/include/ulib/utility/uhttp.h @@ -574,6 +574,7 @@ public: static UString* htdigest; static bool digest_authentication; // authentication method (digest|basic) static UString* user_authentication; + static time_t htdigest_mtime, htpasswd_mtime; static UString getUserAuthentication() { return *user_authentication; } @@ -1511,6 +1512,7 @@ private: static void manageDataForCache(const UString& basename, const UString& suffix) U_NO_EXPORT; static bool checkDataSession(const UString& token, time_t expire, UString* data) U_NO_EXPORT; static void putDataInCache(const UString& path, const UString& fmt, UString& content) U_NO_EXPORT; + static uint32_t checkPasswd(UFileCacheData* ptr_file_data, UString& fpasswd, const UString& line) U_NO_EXPORT; static void addContentLengthToHeader(UString& header, char* ptr, uint32_t size, const char* pEndHeader = U_NULLPTR) U_NO_EXPORT; static void setDataInCache(const UString& fmt, const UString& content, const char* encoding, uint32_t encoding_len) U_NO_EXPORT; static bool processAuthorization(const char* ptr = U_NULLPTR, uint32_t sz = 0, const char* pattern = U_NULLPTR, uint32_t len = 0) U_NO_EXPORT; diff --git a/src/ulib/string.cpp b/src/ulib/string.cpp index ec802b71..08fb43b8 100644 --- a/src/ulib/string.cpp +++ b/src/ulib/string.cpp @@ -86,6 +86,8 @@ const UString* UString::str_ulib_header; const UString* UString::str_storage_keyid; const UString* UString::str_websocket_key; const UString* UString::str_websocket_prot; +const UString* UString::str_htpasswd; +const UString* UString::str_htdigest; // QUERY PARSER const UString* UString::str_p1; const UString* UString::str_p2; @@ -179,9 +181,9 @@ const UString* UString::str_ULib; #endif #ifdef U_HTTP2_DISABLE -static ustringrep stringrep_storage[72] = { +static ustringrep stringrep_storage[74] = { #else -static ustringrep stringrep_storage[136] = { +static ustringrep stringrep_storage[138] = { #endif { U_STRINGREP_FROM_CONSTANT("host") }, { U_STRINGREP_FROM_CONSTANT("chunked") }, @@ -239,6 +241,8 @@ static ustringrep stringrep_storage[136] = { { U_STRINGREP_FROM_CONSTANT("StiD") }, { U_STRINGREP_FROM_CONSTANT("Sec-WebSocket-Key") }, { U_STRINGREP_FROM_CONSTANT("Sec-WebSocket-Protocol") }, + { U_STRINGREP_FROM_CONSTANT("../.htpasswd") }, + { U_STRINGREP_FROM_CONSTANT("../.htdigest") }, // QUERY PARSER { U_STRINGREP_FROM_CONSTANT("(") }, { U_STRINGREP_FROM_CONSTANT(")") }, @@ -458,7 +462,9 @@ void UString::str_allocate(int which) U_INTERNAL_ASSERT_EQUALS(str_ulib_header, U_NULLPTR) U_INTERNAL_ASSERT_EQUALS(str_storage_keyid, U_NULLPTR) U_INTERNAL_ASSERT_EQUALS(str_websocket_key, U_NULLPTR) - U_INTERNAL_ASSERT_EQUALS(str_websocket_prot, U_NULLPTR) + U_INTERNAL_ASSERT_EQUALS(str_websocket_key, U_NULLPTR) + U_INTERNAL_ASSERT_EQUALS(str_htpasswd, U_NULLPTR) + U_INTERNAL_ASSERT_EQUALS(str_htdigest, U_NULLPTR) U_NEW_ULIB_STRING(str_ctype_tsa, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+0)); U_NEW_ULIB_STRING(str_ctype_txt, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+1)); @@ -469,6 +475,8 @@ void UString::str_allocate(int which) U_NEW_ULIB_STRING(str_storage_keyid, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+6)); U_NEW_ULIB_STRING(str_websocket_key, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+7)); U_NEW_ULIB_STRING(str_websocket_prot, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+8)); + U_NEW_ULIB_STRING(str_htpasswd, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+9)); + U_NEW_ULIB_STRING(str_htdigest, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP+10)); } else if ((which & STR_ALLOCATE_QUERY_PARSER) != 0) { @@ -522,7 +530,7 @@ void UString::str_allocate(int which) else if ((which & STR_ALLOCATE_HTTP2) != 0) { U_INTERNAL_ASSERT_EQUALS(str_authority, U_NULLPTR) - U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 136) + U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 138) U_NEW_ULIB_STRING(str_authority, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+0)); U_NEW_ULIB_STRING(str_method, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+1)); @@ -590,7 +598,7 @@ void UString::str_allocate(int which) U_NEW_ULIB_STRING(str_ULib, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+63)); } #else - U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 72) + U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 74) #endif } diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index f16ef39c..a9113d9a 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -81,6 +81,8 @@ URDB* UHTTP::db_not_found; off_t UHTTP::range_size; off_t UHTTP::range_start; UFile* UHTTP::file; +time_t UHTTP::htdigest_mtime; +time_t UHTTP::htpasswd_mtime; UString* UHTTP::ext; UString* UHTTP::etag; UString* UHTTP::geoip; @@ -7472,6 +7474,98 @@ next: handlerResponse(); } +U_NO_EXPORT uint32_t UHTTP::checkPasswd(UHTTP::UFileCacheData* ptr_file_data, UString& fpasswd, const UString& line) +{ + U_TRACE(0, "UHTTP::checkPasswd(%p,%V,%V)", ptr_file_data, fpasswd.rep, line.rep) + + // s.casazza:{SHA}Lkii1ZE7k.....\n + // s.casazza:Protected Area:b9ee2af50be37...........\n + + uint32_t pos = fpasswd.find(line); + + if (pos == U_NOT_FOUND || + (pos > 0 && line[pos-1] != '\n')) + { + U_INTERNAL_DUMP("digest_authentication = %b htpasswd = %p", digest_authentication, htpasswd) + + if (ptr_file_data) + { + U_ASSERT(cache_file->key()->equal(u_buffer)) + + UString lpathname = cache_file->getKey(); + + UFile tmp(lpathname); + + if (tmp.open() && + (tmp.st_mtime = ptr_file_data->mtime, tmp.isModified())) + { + ptr_file_data->array->erase(0); + + fpasswd = tmp.getContent(true, false, true); + + ptr_file_data->array->push_back(fpasswd); + + U_SRV_LOG("File data users permission: %V reloaded - %u bytes", lpathname.rep, fpasswd.size()); + + goto next; + } + + tmp.close(); + } + else + { + if (digest_authentication) + { + U_INTERNAL_ASSERT(htdigest) + + UFile tmp(*UString::str_htdigest); + + if (tmp.open() && + (tmp.st_mtime = htdigest_mtime, tmp.isModified())) + { + fpasswd = *htdigest = tmp.getContent(true, false, true); + + U_SRV_LOG("File data users permission: ../.htdigest reloaded - %u bytes", fpasswd.size()); + + goto next; + } + + tmp.close(); + } + else + { + U_INTERNAL_ASSERT(htpasswd) + + UFile tmp(*UString::str_htpasswd); + + if (tmp.open() && + (tmp.st_mtime = htpasswd_mtime, tmp.isModified())) + { + fpasswd = *htpasswd = tmp.getContent(true, false, true); + + U_SRV_LOG("File data users permission: ../.htpasswd reloaded - %u bytes", fpasswd.size()); + + goto next; + } + + tmp.close(); + } + } + + U_RETURN(U_NOT_FOUND); + +next: pos = fpasswd.find(line); + + if (pos == U_NOT_FOUND || + (pos > 0 && line[pos-1] != '\n')) + { + U_RETURN(U_NOT_FOUND); + } + } + + U_RETURN(pos); +} + U_NO_EXPORT bool UHTTP::processAuthorization(const char* request, uint32_t sz, const char* pattern, uint32_t len) { U_TRACE(0, "UHTTP::processAuthorization(%.*S,%u,%.*S,%u)", sz, request, sz, len, pattern, len) @@ -7712,7 +7806,7 @@ U_NO_EXPORT bool UHTTP::processAuthorization(const char* request, uint32_t sz, c // s.casazza:Protected Area:b9ee2af50be37...........\n - pos = fpasswd.find(buffer); + pos = checkPasswd(ptr_file_data, fpasswd, buffer); if (pos == U_NOT_FOUND) goto end; @@ -7771,7 +7865,7 @@ U_NO_EXPORT bool UHTTP::processAuthorization(const char* request, uint32_t sz, c // s.casazza:{SHA}Lkii1ZE7k.....\n - if (fpasswd.find(line) != U_NOT_FOUND) result = true; + if (checkPasswd(ptr_file_data, fpasswd, line) != U_NOT_FOUND) result = true; } } } @@ -8773,6 +8867,9 @@ U_NO_EXPORT void UHTTP::manageDataForCache(const UString& basename, const UStrin if (bpasswd) { U_INTERNAL_ASSERT_EQUALS(htpasswd, U_NULLPTR) + U_ASSERT_EQUALS(lpathname, *UString::str_htpasswd) + + htpasswd_mtime = file->st_mtime; U_NEW_STRING(htpasswd, UString(content)); @@ -8782,6 +8879,9 @@ U_NO_EXPORT void UHTTP::manageDataForCache(const UString& basename, const UStrin { U_INTERNAL_ASSERT(bdigest) U_INTERNAL_ASSERT_EQUALS(htdigest, U_NULLPTR) + U_ASSERT_EQUALS(lpathname, *UString::str_htdigest) + + htdigest_mtime = file->st_mtime; U_NEW_STRING(htdigest, UString(content)); @@ -11566,17 +11666,13 @@ bool UHTTP::checkIfSourceHasChangedAndCompileUSP() if (suffix.empty()) { - struct stat st; char buffer[U_PATH_MAX+1]; if (getFileCachePointer(buffer, u__snprintf(buffer, U_PATH_MAX, U_CONSTANT_TO_PARAM("%.*s.usp"), U_FILE_TO_TRACE(*file))) && - U_SYSCALL(stat, "%S,%p", buffer, &st) == 0 && - st.st_mtime > file_data->mtime) + UFile::isModified(buffer, file_data->mtime)) { U_INTERNAL_ASSERT_POINTER(usp) - U_INTERNAL_DUMP("st.st_mtime = %#3D file_data->mtime = %#3D", st.st_mtime, file_data->mtime) - compile: if (compileUSP(ptr, len) == false) { err: setInternalError(); diff --git a/tests/examples/TSA/tsaserial b/tests/examples/TSA/tsaserial index 04519668..648933ea 100644 --- a/tests/examples/TSA/tsaserial +++ b/tests/examples/TSA/tsaserial @@ -1 +1 @@ -01D3 +01E1 diff --git a/tests/ulib/test_json.cpp b/tests/ulib/test_json.cpp index e34494ce..2e98b704 100644 --- a/tests/ulib/test_json.cpp +++ b/tests/ulib/test_json.cpp @@ -143,6 +143,16 @@ U_EXPORT main (int argc, char* argv[], char* env[]) char buffer[4096]; uint32_t i, n, params[2] = { 2, 1 }; UString result(U_CAPACITY), result1, filename, content, array; + + /* + double lat, lon; + + content = U_STRING_FROM_CONSTANT("{ \"joinedAtLon\" : \"-73.968285\", \"token\" : \"A8Ngwl5\", \"joinedAtLat\" : \"40.785091\", \"number\" : \"+12016752089\" }"); + (void) U_JFIND(content, "joinedAtLat", lat); + (void) U_JFIND(content, "joinedAtLon", lon); + + U_INTERNAL_DUMP("lat = %f lon = %f", lat, lon) + */ UValue::jsonParseFlags = 2;