]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/acl/external/session/ext_session_acl.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / acl / external / session / ext_session_acl.cc
index 600230d1731eab05b86c6d7d56fd04fa0f588c2f..8fcffccbb6d315ac21520e0eccb8d796c351b37d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -29,7 +29,7 @@
 #if HAVE_CONFIG_H
 #include "squid.h"
 #endif
-#include "helpers/defines.h"
+#include "helper/protocol_defines.h"
 
 #include <cstdlib>
 #include <cstring>
@@ -43,6 +43,9 @@
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
+#if HAVE_TDB_H
+#include <tdb.h>
+#endif
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -60,8 +63,38 @@ static int fixed_timeout = 0;
 char *db_path = NULL;
 const char *program_name;
 
+#if USE_BERKLEYDB
 DB *db = NULL;
 DB_ENV *db_env = NULL;
+typedef DBT DB_ENTRY;
+
+#elif USE_TRIVIALDB
+TDB_CONTEXT *db = nullptr;
+typedef TDB_DATA DB_ENTRY;
+
+#else
+#error "Either Berkeley DB or Trivial DB must be available"
+#endif
+
+static void
+shutdown_db()
+{
+    if (db) {
+#if USE_BERKLEYDB
+        db->close(db, 0);
+    }
+    if (db_env) {
+        db_env->close(db_env, 0);
+
+#elif USE_TRIVIALDB
+        if (tdb_close(db) != 0) {
+            fprintf(stderr, "%s| WARNING: error closing session db '%s'\n", program_name, db_path);
+            exit(EXIT_FAILURE);
+        }
+#endif
+    }
+    xfree(db_path);
+}
 
 static void init_db(void)
 {
@@ -70,83 +103,155 @@ static void init_db(void)
     if (db_path) {
         if (!stat(db_path, &st_buf)) {
             if (S_ISDIR (st_buf.st_mode)) {
+#if USE_BERKLEYDB
                 /* If directory then open database environment. This prevents sync problems
                     between different processes. Otherwise fallback to single file */
                 db_env_create(&db_env, 0);
-                if (db_env->open(db_env, db_path, DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK , 0666)) {
+                if (db_env->open(db_env, db_path, DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK, 0666)) {
                     fprintf(stderr, "FATAL: %s: Failed to open database environment in '%s'\n", program_name, db_path);
                     db_env->close(db_env, 0);
-                    exit(1);
+                    exit(EXIT_FAILURE);
                 }
                 db_create(&db, db_env, 0);
+#elif USE_TRIVIALDB
+                std::string newPath(db_path);
+                newPath.append("session", 7);
+                db_path = xstrdup(newPath.c_str());
+#endif
             }
         }
     }
 
+#if USE_BERKLEYDB
     if (db_env) {
         if (db->open(db, NULL, "session", NULL, DB_BTREE, DB_CREATE, 0666)) {
             fprintf(stderr, "FATAL: %s: Failed to open db file '%s' in dir '%s'\n",
                     program_name, "session", db_path);
             db_env->close(db_env, 0);
-            exit(1);
+            exit(EXIT_FAILURE);
         }
     } else {
         db_create(&db, NULL, 0);
         if (db->open(db, NULL, db_path, NULL, DB_BTREE, DB_CREATE, 0666)) {
-            fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
-            exit(1);
+            db = nullptr;
         }
     }
+#elif USE_TRIVIALDB
+#if _SQUID_FREEBSD_ && !defined(O_DSYNC)
+    // FreeBSD lacks O_DSYNC, O_SYNC is closest to correct behaviour
+#define O_DSYNC O_SYNC
+#endif
+    db = tdb_open(db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT|O_DSYNC, 0666);
+#endif
+    if (!db) {
+        fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
+        shutdown_db();
+        exit(EXIT_FAILURE);
+    }
 }
 
-static void shutdown_db(void)
+int session_is_active = 0;
+
+static size_t
+dataSize(DB_ENTRY *data)
 {
-    db->close(db, 0);
-    if (db_env) {
-        db_env->close(db_env, 0);
-    }
+#if USE_BERKLEYDB
+    return data->size;
+#elif USE_TRIVIALDB
+    return data->dsize;
+#endif
 }
 
-int session_is_active = 0;
+static bool
+fetchKey(/*const*/ DB_ENTRY &key, DB_ENTRY *data)
+{
+#if USE_BERKLEYDB
+    return (db->get(db, nullptr, &key, data, 0) == 0);
+#elif USE_TRIVIALDB
+    // NP: API says returns NULL on errors, but return is a struct type WTF??
+    *data = tdb_fetch(db, key);
+    return (data->dptr != nullptr);
+#endif
+}
+
+static void
+deleteEntry(/*const*/ DB_ENTRY &key)
+{
+#if USE_BERKLEYDB
+    db->del(db, nullptr, &key, 0);
+#elif USE_TRIVIALDB
+    tdb_delete(db, key);
+#endif
+}
+
+static void
+copyValue(void *dst, const DB_ENTRY *src, size_t sz)
+{
+#if USE_BERKLEYDB
+    memcpy(dst, src->data, sz);
+#elif USE_TRIVIALDB
+    memcpy(dst, src->dptr, sz);
+#endif
+}
 
 static int session_active(const char *details, size_t len)
 {
+#if USE_BERKLEYDB
     DBT key = {0};
     DBT data = {0};
     key.data = (void *)details;
     key.size = len;
-    if (db->get(db, NULL, &key, &data, 0) == 0) {
+#elif USE_TRIVIALDB
+    TDB_DATA key;
+    TDB_DATA data;
+#endif
+    if (fetchKey(key, &data)) {
         time_t timestamp;
-        if (data.size != sizeof(timestamp)) {
+        if (dataSize(&data) != sizeof(timestamp)) {
             fprintf(stderr, "ERROR: %s: CORRUPTED DATABASE (%s)\n", program_name, details);
-            db->del(db, NULL, &key, 0);
+            deleteEntry(key);
             return 0;
         }
-        memcpy(&timestamp, data.data, sizeof(timestamp));
+        copyValue(&timestamp, &data, sizeof(timestamp));
         if (timestamp + session_ttl >= time(NULL))
             return 1;
     }
     return 0;
 }
 
-static void session_login(const char *details, size_t len)
+static void
+session_login(/*const*/ char *details, size_t len)
 {
-    DBT key = {0};
-    DBT data = {0};
-    key.data = (void *)details;
+    DB_ENTRY key = {0};
+    DB_ENTRY data = {0};
+    time_t now = time(0);
+#if USE_BERKLEYDB
+    key.data = static_cast<decltype(key.data)>(details);
     key.size = len;
-    time_t now = time(NULL);
     data.data = &now;
     data.size = sizeof(now);
     db->put(db, NULL, &key, &data, 0);
+#elif USE_TRIVIALDB
+    key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+    key.dsize = len;
+    data.dptr = reinterpret_cast<decltype(data.dptr)>(&now);
+    data.dsize = sizeof(now);
+    tdb_store(db, key, data, 0);
+#endif
 }
 
-static void session_logout(const char *details, size_t len)
+static void
+session_logout(/*const*/ char *details, size_t len)
 {
-    DBT key = {0};
-    key.data = (void *)details;
+    DB_ENTRY key = {0};
+#if USE_BERKLEYDB
+    key.data = static_cast<decltype(key.data)>(details);
     key.size = len;
-    db->del(db, NULL, &key, 0);
+#elif USE_TRIVIALDB
+    key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+    key.dsize = len;
+#endif
+    deleteEntry(key);
 }
 
 static void usage(void)
@@ -173,14 +278,14 @@ int main(int argc, char **argv)
             session_ttl = strtol(optarg, NULL, 0);
             break;
         case 'b':
-            db_path = optarg;
+            db_path = xstrdup(optarg);
             break;
         case 'a':
             default_action = 0;
             break;
         case '?':
             usage();
-            exit(0);
+            exit(EXIT_SUCCESS);
             break;
         }
     }
@@ -194,10 +299,10 @@ int main(int argc, char **argv)
         const char *channel_id = strtok(request, " ");
         char *detail = strtok(NULL, "\n");
         if (detail == NULL) {
-            // Only 1 paramater supplied. We are expecting at least 2 (including the channel ID)
+            // Only 1 parameter supplied. We are expecting at least 2 (including the channel ID)
             fprintf(stderr, "FATAL: %s is concurrent and requires the concurrency option to be specified.\n", program_name);
             shutdown_db();
-            exit(1);
+            exit(EXIT_FAILURE);
         }
         char *lastdetail = strrchr(detail, ' ');
         size_t detail_len = strlen(detail);
@@ -210,6 +315,11 @@ int main(int argc, char **argv)
                 action = -1;
                 detail_len = (size_t)(lastdetail-detail);
                 *lastdetail = '\0';
+            } else if (!default_action && strcmp(lastdetail, " -") == 0) {
+                // no action; LOGIN/LOGOUT not supplied
+                // but truncate the '-' %DATA value given by Squid-4 and later
+                detail_len = (size_t)(lastdetail-detail);
+                *lastdetail = '\0';
             }
         }
         if (action == -1) {
@@ -231,6 +341,6 @@ int main(int argc, char **argv)
         }
     }
     shutdown_db();
-    return 0;
+    return EXIT_SUCCESS;
 }