From: Andrew Beverley Date: Sun, 23 Oct 2011 01:07:46 +0000 (-0600) Subject: ext_session_acl: version 1.2 X-Git-Tag: BumpSslServerFirst.take01~84 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e8f57e04f3ff39428f2adec9d0584fe5290767e;p=thirdparty%2Fsquid.git ext_session_acl: version 1.2 This patch makes the following changes to the session helper: - Removes support for Berkeley DB 1.85 - Adds support for the current Berkeley DB (db.h) - Adds support for a DB environment (if a directory is specified as the path then an environment is created). This gives better synchronisation within multiple processes - Fixes a bug with active mode where LOGIN/LOGOUT did not write to the DB --- diff --git a/helpers/external_acl/session/ext_session_acl.8 b/helpers/external_acl/session/ext_session_acl.8 index eecf93393e..40788fbfb2 100644 --- a/helpers/external_acl/session/ext_session_acl.8 +++ b/helpers/external_acl/session/ext_session_acl.8 @@ -1,11 +1,11 @@ -.if !'po4a'hide' .TH ext_session_acl 8 "19 September 2011" +.if !'po4a'hide' .TH ext_session_acl 8 "9 October 2011" . .SH NAME .if !'po4a'hide' .B ext_session_acl .if !'po4a'hide' \- Squid session tracking external acl helper. .PP -Version 1.1 +Version 1.2 . .SH SYNOPSIS .if !'po4a'hide' .B ext_session_acl @@ -52,9 +52,15 @@ will reset the session and timeout. .if !'po4a'hide' .TP .if !'po4a'hide' .B "\-b path" .B Path -to persistent database. If not specified the session details -will be kept in memory only and all sessions will reset each time -Squid restarts its helpers (Squid restart or rotation of logs). +to persistent database. If a file is specified then that single file is +used as the database. If a path is specified, a Berkeley DB database +environment is created within the directory. The advantage of the latter +is better database support between multiple instances of the session +helper. Using multiple instances of the session helper with a single +database file will cause synchronisation problems between processes. +If this option is not specified the session details will be kept in +memory only and all sessions will reset each time Squid restarts its +helpers (Squid restart or rotation of logs). . .if !'po4a'hide' .TP .if !'po4a'hide' .B \-a @@ -91,6 +97,7 @@ to display a session startup page and then redirect the user back to the request .SH AUTHOR This program and documentation was written by .if !'po4a'hide' .I Henrik Nordstrom +.if !'po4a'hide' .I Andrew Beverley . .SH COPYRIGHT This program and documentation is copyright to the authors named above. diff --git a/helpers/external_acl/session/ext_session_acl.cc b/helpers/external_acl/session/ext_session_acl.cc index b51106c2de..93b5937162 100644 --- a/helpers/external_acl/session/ext_session_acl.cc +++ b/helpers/external_acl/session/ext_session_acl.cc @@ -23,18 +23,21 @@ #endif #include "helpers/defines.h" -#include -#include +#if HAVE_DB_H +#include +#endif #include +#if HAVE_GETOPT_H +#include +#endif #include #include -#if HAVE_UNISTD_H -#include -#endif #include +#include +#include #include -#if HAVE_GETOPT_H -#include +#if HAVE_UNISTD_H +#include #endif /* At this point all Bit Types are already defined, so we must @@ -45,45 +48,71 @@ #define __BIT_TYPES_DEFINED__ #endif -#if HAVE_DB_185_H -#include -#elif HAVE_DB_H -#include -#endif - static int session_ttl = 3600; static int fixed_timeout = 0; char *db_path = NULL; const char *program_name; DB *db = NULL; +DB_ENV *db_env = NULL; static void init_db(void) { - db = dbopen(db_path, O_CREAT | O_RDWR, 0666, DB_BTREE, NULL); - if (!db) { - fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path); - exit(1); + struct stat st_buf; + + if (db_path) { + if (!stat(db_path, &st_buf)) { + if (S_ISDIR (st_buf.st_mode)) { + /* 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)) { + fprintf(stderr, "FATAL: %s: Failed to open database environment in '%s'\n", program_name, db_path); + db_env->close(db_env, 0); + exit(1); + } + db_create(&db, db_env, 0); + } + } + } + + 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); + } + } 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); + } } } static void shutdown_db(void) { - db->close(db); + db->close(db, 0); + if (db_env) { + db_env->close(db_env, 0); + } } int session_is_active = 0; static int session_active(const char *details, size_t len) { - DBT key, data; + DBT key = {0}; + DBT data = {0}; key.data = (void *)details; key.size = len; - if (db->get(db, &key, &data, 0) == 0) { + if (db->get(db, NULL, &key, &data, 0) == 0) { time_t timestamp; if (data.size != sizeof(timestamp)) { fprintf(stderr, "ERROR: %s: CORRUPTED DATABASE (%s)\n", program_name, details); - db->del(db, &key, 0); + db->del(db, NULL, &key, 0); return 0; } memcpy(×tamp, data.data, sizeof(timestamp)); @@ -95,22 +124,22 @@ static int session_active(const char *details, size_t len) static void session_login(const char *details, size_t len) { - DBT key, data; - time_t now = time(NULL); + DBT key = {0}; + DBT data = {0}; key.data = (void *)details; key.size = len; + time_t now = time(NULL); data.data = &now; data.size = sizeof(now); - db->put(db, &key, &data, 0); - db->sync(db, 0); + db->put(db, NULL, &key, &data, 0); } static void session_logout(const char *details, size_t len) { - DBT key; + DBT key = {0}; key.data = (void *)details; key.size = len; - db->del(db, &key, 0); + db->del(db, NULL, &key, 0); } static void usage(void) @@ -156,21 +185,24 @@ int main(int argc, char **argv) while (fgets(request, HELPER_INPUT_BUFFER, stdin)) { int action = 0; const char *channel_id = strtok(request, " "); - const char *detail = strtok(NULL, "\n"); + char *detail = strtok(NULL, "\n"); if (detail == NULL) { // Only 1 paramater 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); } - const char *lastdetail = strrchr(detail, ' '); + char *lastdetail = strrchr(detail, ' '); size_t detail_len = strlen(detail); if (lastdetail) { if (strcmp(lastdetail, " LOGIN") == 0) { action = 1; detail_len = (size_t)(lastdetail-detail); + *lastdetail = '\0'; } else if (strcmp(lastdetail, " LOGOUT") == 0) { action = -1; detail_len = (size_t)(lastdetail-detail); + *lastdetail = '\0'; } } if (action == -1) { diff --git a/src/squid.8.in b/src/squid.8.in index cba6191c9d..4ed2d91972 100644 --- a/src/squid.8.in +++ b/src/squid.8.in @@ -265,7 +265,7 @@ Report ideas for new improvements to the .if !'po4a'hide' .B pam_auth "(8), " .if !'po4a'hide' .B squid_ldap_auth "(8), " .if !'po4a'hide' .B squid_ldap_group "(8), " -.if !'po4a'hide' .B squid_session "(8), " +.if !'po4a'hide' .B ext_session_acl "(8), " .if !'po4a'hide' .B squid_unix_group "(8), " .br The Squid FAQ wiki