summaryrefslogtreecommitdiffstats
path: root/src/squark-auth-ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/squark-auth-ip.c')
-rw-r--r--src/squark-auth-ip.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/squark-auth-ip.c b/src/squark-auth-ip.c
new file mode 100644
index 0000000..3cdea0b
--- /dev/null
+++ b/src/squark-auth-ip.c
@@ -0,0 +1,218 @@
+/* squark-auth-ip.c - Squid User Authentication and Rating Kit
+ * An external acl helper for Squid which collects authentication
+ * information about an IP-address from local shared memory database.
+ *
+ * Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "blob.h"
+#include "authdb.h"
+#include "filterdb.h"
+
+#define DO_LOGIN -1
+#define DO_OVERRIDE -2
+#define DO_PRINT -3
+#define DO_LOGOUT -4
+
+static int running = 1;
+static struct sqdb db;
+static struct authdb adb;
+static struct authdb_config adbc;
+static blob_t space = BLOB_STR_INIT(" ");
+static blob_t lf = BLOB_STR_INIT("\n");
+static time_t now;
+
+static void handle_line(blob_t line)
+{
+ char reply[128];
+ blob_t b, id, ipaddr;
+ struct authdb_entry entry;
+ sockaddr_any addr;
+ void *token;
+ int auth_ok = 0;
+
+ id = blob_pull_cspn(&line, space);
+ blob_pull_spn(&line, space);
+ ipaddr = blob_pull_cspn(&line, space);
+
+ if (addr_parse(ipaddr, &addr)) {
+ token = authdb_get(&adb, &addr, &entry, 1);
+
+ if (authdb_check_login(token, &entry, BLOB_NULL, now))
+ auth_ok = 1;
+ }
+
+ b = BLOB_BUF(reply);
+ blob_push(&b, id);
+ if (auth_ok) {
+ blob_push(&b, BLOB_STR(" OK user="));
+ blob_push(&b, BLOB_STRLEN(entry.p.login_name));
+ blob_push(&b, BLOB_PTR_LEN("\n", 1));
+ } else {
+ blob_push(&b, BLOB_STR(" ERR\n"));
+ }
+
+ b = blob_pushed(BLOB_BUF(reply), b);
+ write(STDOUT_FILENO, b.ptr, b.len);
+}
+
+static void read_input(void)
+{
+ static char buffer[256];
+ static blob_t left;
+
+ blob_t b, line;
+ int r;
+
+ if (blob_is_null(left))
+ left = BLOB_BUF(buffer);
+
+ r = read(STDIN_FILENO, left.ptr, left.len);
+ if (r < 0)
+ return;
+ if (r == 0) {
+ running = 0;
+ return;
+ }
+ left.ptr += r;
+ left.len -= r;
+
+ now = time(NULL);
+
+ b = blob_pushed(BLOB_BUF(buffer), left);
+ do {
+ line = blob_pull_cspn(&b, lf);
+ if (!blob_pull_matching(&b, lf))
+ return;
+
+ handle_line(line);
+
+ if (b.len) {
+ memcpy(buffer, b.ptr, b.len);
+ b.ptr = buffer;
+ }
+ left = BLOB_PTR_LEN(buffer + b.len, sizeof(buffer) - b.len);
+ } while (b.len);
+}
+
+#define DUMPPAR(b, name, fn) \
+ do { \
+ blob_push(b, BLOB_STR("squark_" name "='")); \
+ fn; \
+ blob_push(b, BLOB_STR("'; ")); \
+ } while (0)
+
+int main(int argc, char **argv)
+{
+ int opt;
+ sockaddr_any ipaddr = { .any.sa_family = AF_UNSPEC };
+ blob_t ip = BLOB_NULL, username = BLOB_NULL;
+
+ while ((opt = getopt(argc, argv, "i:u:olpL")) != -1) {
+ switch (opt) {
+ case 'i':
+ ip = BLOB_STRLEN(optarg);
+ if (!addr_parse(ip, &ipaddr)) {
+ fprintf(stderr, "'%s' does not look like IP-address\n",
+ optarg);
+ return 1;
+ }
+ break;
+ case 'u':
+ username = BLOB_STRLEN(optarg);
+ break;
+ case 'o':
+ running = DO_OVERRIDE;
+ break;
+ case 'l':
+ running = DO_LOGIN;
+ break;
+ case 'p':
+ running = DO_PRINT;
+ break;
+ case 'L':
+ running = DO_LOGOUT;
+ break;
+ }
+ }
+
+ now = time(NULL);
+ sqdb_open(&db, "/var/lib/squark/squark.db");
+ authdb_open(&adb, &adbc, &db);
+
+ if (running < 0) {
+ struct authdb_entry entry;
+ void *token;
+
+ if (ipaddr.any.sa_family == AF_UNSPEC) {
+ fprintf(stderr, "IP-address not specified\n");
+ return 2;
+ }
+
+ token = authdb_get(&adb, &ipaddr, &entry, 1);
+ if (token == NULL) {
+ fprintf(stderr, "Failed to get authdb record\n");
+ return 3;
+ }
+
+ switch (running) {
+ case DO_LOGIN:
+ if (blob_is_null(username)) {
+ fprintf(stderr, "Username not specified\n");
+ return 2;
+ }
+ authdb_clear_entry(&entry);
+ memcpy(entry.p.login_name, username.ptr, username.len);
+ authdb_commit_login(token, &entry, now, &adbc);
+ break;
+ case DO_OVERRIDE:
+ if (authdb_check_login(token, &entry, username, now))
+ authdb_commit_override(token, &entry, now);
+ break;
+ case DO_PRINT: {
+ char buf[512];
+ blob_t b = BLOB_BUF(buf);
+
+ DUMPPAR(&b, "ip_address",
+ addr_push_hostaddr(&b, &ipaddr));
+ DUMPPAR(&b, "username",
+ blob_push(&b, BLOB_BUF(entry.p.login_name)));
+ DUMPPAR(&b, "mac_address",
+ blob_push_hexdump(&b, BLOB_BUF(entry.p.mac_address)));
+ DUMPPAR(&b, "login_time",
+ blob_push_ctime(&b, entry.p.login_time));
+ DUMPPAR(&b, "activity_time",
+ blob_push_ctime(&b, entry.last_activity_time));
+ DUMPPAR(&b, "override_time",
+ blob_push_ctime(&b, entry.override_time));
+ DUMPPAR(&b, "block_categories",
+ blob_push_hexdump(&b, BLOB_BUF(&entry.p.block_categories)));
+ DUMPPAR(&b, "hard_block_categories",
+ blob_push_hexdump(&b, BLOB_BUF(&entry.p.hard_block_categories)));
+ blob_push(&b, BLOB_STR("\n"));
+ b = blob_pushed(BLOB_BUF(buf), b);
+ fwrite(b.ptr, b.len, 1, stdout);
+ break;
+ }
+ case DO_LOGOUT:
+ if (authdb_check_login(token, &entry, username, now))
+ authdb_commit_logout(token);
+ break;
+ }
+ } else {
+ while (running)
+ read_input();
+ }
+
+ authdb_close(&adb);
+ sqdb_close(&db);
+}