]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
ip_user external_acl helper by Rodrigo Campos
authorhno <>
Sun, 23 Jun 2002 20:25:16 +0000 (20:25 +0000)
committerhno <>
Sun, 23 Jun 2002 20:25:16 +0000 (20:25 +0000)
helpers/external_acl/ip_user/README [new file with mode: 0644]
helpers/external_acl/ip_user/dict.c [new file with mode: 0644]
helpers/external_acl/ip_user/example-deny_all_but.conf [new file with mode: 0644]
helpers/external_acl/ip_user/example.conf [new file with mode: 0644]
helpers/external_acl/ip_user/ip_user.h [new file with mode: 0644]
helpers/external_acl/ip_user/license [new file with mode: 0644]
helpers/external_acl/ip_user/main.c [new file with mode: 0644]
helpers/external_acl/ip_user/match.c [new file with mode: 0644]

diff --git a/helpers/external_acl/ip_user/README b/helpers/external_acl/ip_user/README
new file mode 100644 (file)
index 0000000..eaa697a
--- /dev/null
@@ -0,0 +1,42 @@
+$Id: README,v 1.1 2002/06/23 14:25:16 hno Exp $
+
+README file for ip_user_check, an external helper for the 
+Squid external acl scheme.
+
+It works by reading a pair composed by an ip address and an username
+on STDIN and matching it against a configuration file.
+
+The configuration for the external ACL should be:
+
+external_acl_type type-name %SRC %LOGIN /path/to/ip_user_check -f /path/to/config.file
+
+If the program finds a matching username/ip in the configuration file, 
+it returns `OK', or `ERR' otherwise.
+
+The usage for the program is:
+
+ip_user_check -f <configuration_file>
+
+
+The configuration file format is as follows:
+
+ip_addr[/mask]         user|@group|ALL|NONE
+
+Where ip_addr is a dotted quad format IP address, the mask
+must be in dotted quad format too.
+
+When the second parameter is prefixed with an @, the program will lookup in the
+/etc/group entry for the specified username.
+
+There are other two directives, `ALL' and `NONE', which mean "any user on this ip
+address may authenticate" or "no user on this ip address may authenticate".
+
+TODO
+- Deny operator, to create `allow all but' rules
+- Check for a valid user in the OS
+- Accept decimal format netmasks 
+
+
+--
+Rodrigo Campos
+rodrigo@geekbunker.org
diff --git a/helpers/external_acl/ip_user/dict.c b/helpers/external_acl/ip_user/dict.c
new file mode 100644 (file)
index 0000000..cc3fbdd
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id: dict.c,v 1.1 2002/06/23 14:25:17 hno Exp $ 
+* Copyright (C) 2002 Rodrigo Campos
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Author: Rodrigo Campos (rodrigo@geekbunker.org)
+* 
+*/
+                         
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "ip_user.h"
+
+#ifndef DEBUG
+#undef DEBUG
+#endif
+
+
+/* This function parses the dictionary file and loads it 
+ * in memory. All IP addresses are processed with a bitwise AND
+ * with their netmasks before they are stored.
+ * If there´s no netmask (no /) in the in the lhs , a mask
+ * 255.255.255.255 is assumed.
+ * It returns a pointer to the first entry of the linked list
+ */
+struct ip_user_dict *
+load_dict (FILE * FH)
+{
+  struct ip_user_dict *current_entry;  /* the structure used to
+                                          store data */
+  struct ip_user_dict *first_entry = NULL;     /* the head of the
+                                                  linked list */
+  char line[BUFSIZE];          /* the buffer for the lines read
+                                  from the dict file */
+  char *cp;                    /* a char pointer used to parse
+                                  each line */
+  char *username;              /* for the username */
+  char *tmpbuf;                        /* for the address before the
+                                  bitwise AND */
+
+  /* the pointer to the first entry in the linked list */
+  first_entry = malloc (sizeof (struct ip_user_dict));
+  current_entry = first_entry;
+
+  while ((cp = fgets (line, sizeof (line), FH)) != NULL) {
+                 if (line[0] == '#') {
+                                 continue;
+                 }
+    if ((cp = strchr (line, '\n')) != NULL) {
+      /* chop \n characters */
+      *cp = '\0';
+    }
+    if ((cp = strtok (line, "\t ")) != NULL) {
+      /* get the username */
+      username = strtok (NULL, "\t ");
+      /* look for a netmask */
+      if ((cp = strtok (line, "/")) != NULL) {
+       /* store the ip address in a temporary buffer */
+       tmpbuf = cp;
+       cp = strtok (NULL, "/");
+       if (cp != NULL) {
+         /* if we have a slash in the lhs, we have a netmask */
+         current_entry->netmask = (inet_addr (cp));
+         current_entry->address =
+           (((inet_addr (tmpbuf))) & current_entry->netmask);
+       } else {
+         /* when theres no slash, we figure the netmask is /32 */
+         current_entry->address = (inet_addr (tmpbuf));
+         current_entry->netmask = (inet_addr ("255.255.255.255"));
+       }
+      }
+      /* get space for the username */
+      current_entry->username =
+       calloc (strlen (username) + 1, sizeof (char));
+      strcpy (current_entry->username, username);
+
+      /* get space and point current_entry to the new entry */
+      current_entry->next_entry =
+       malloc (sizeof (struct ip_user_dict));
+      current_entry = current_entry->next_entry;
+    }
+
+  }
+
+  /* Return a pointer to the first entry linked list */
+  return first_entry;
+}                              /* load_dict */
+
+/* This function looks for a matching ip/mask in
+ * the dict file loaded in memory.
+ * It returns 1 if it finds a match or 0 if no match is found
+ */
+int
+dict_lookup (struct ip_user_dict *first_entry, char *username,
+            char *address)
+{
+  /* Move the pointer to the first entry of the linked list. */
+  struct ip_user_dict *current_entry = first_entry;
+
+  while (current_entry->username != NULL) {
+#ifdef DEBUG
+    printf ("user: %s\naddr: %lu\nmask: %lu\n\n",
+           current_entry->username, current_entry->address,
+           current_entry->netmask);
+#endif
+
+    if ((inet_addr (address) & (unsigned long) current_entry->
+        netmask) == current_entry->address) {
+      /* If the username contains an @ we assume it´s a group and
+         call the corresponding function */
+      if ((strchr (current_entry->username, '@')) == NULL) {
+       if ((match_user (current_entry->username, username)) == 1)
+         return 1;
+      } else {
+       if ((match_group (current_entry->username, username)) == 1)
+         return 1;
+      }
+    }
+    current_entry = current_entry->next_entry;
+  }
+
+  /* If no match was found we return 0 */
+  return 0;
+}                              /* dict_lookup */
diff --git a/helpers/external_acl/ip_user/example-deny_all_but.conf b/helpers/external_acl/ip_user/example-deny_all_but.conf
new file mode 100644 (file)
index 0000000..a5280b0
--- /dev/null
@@ -0,0 +1,2 @@
+192.168.1.0/255.255.255.0      diniz
+0.0.0.0/0.0.0.0        NONE
diff --git a/helpers/external_acl/ip_user/example.conf b/helpers/external_acl/ip_user/example.conf
new file mode 100644 (file)
index 0000000..f994e90
--- /dev/null
@@ -0,0 +1,39 @@
+# $Id: example.conf,v 1.1 2002/06/23 14:25:17 hno Exp $
+# Lines that begin with a # are ignored
+# The main format is:
+# 
+# Single user
+# ip[/mask]            user
+# 
+# Users that belong to `group´  (/etc/group)
+# ip[/mask]            @group
+#
+# No User from this IP
+# ip[/mask]            NONE
+#
+# All Users from this IP
+# ip[/mask]            ALL
+#
+# IP and MASK must be in dotted quad format.
+#
+# Ths first match wins, so you may create rules that
+# `allow everyone but foo bar´ or
+# `deny everyone but foo bar´
+#
+# Examples:
+# All users from the 192.168.1.0/24 network are allowed
+# 192.168.1.0/255.255.255.0    ALL
+#
+# Users from the 192.168.2.0/24 network are not allowed
+# except for user `boss´ that can authenticate from
+# anywhere
+# 0.0.0.0/0.0.0.0      boss
+# 192.168.2.0/255.255.255.0    NONE
+#
+# User `jayk´ may athenticate only from his station
+# ip address
+# 192.168.3.45 jayk
+#
+# Users of the `tol´ group may authenticate from
+# their VLAN
+# 10.0.0.0/255.255.0.0 @tol
diff --git a/helpers/external_acl/ip_user/ip_user.h b/helpers/external_acl/ip_user/ip_user.h
new file mode 100644 (file)
index 0000000..f8617f4
--- /dev/null
@@ -0,0 +1,39 @@
+/* $Id: ip_user.h,v 1.1 2002/06/23 14:25:17 hno Exp $
+* Copyright (C) 2002 Rodrigo Campos
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Author: Rodrigo Campos (rodrigo@geekbunker.org)
+* 
+*/
+
+
+
+
+struct ip_user_dict
+{
+  unsigned long address;
+  unsigned long netmask;
+  char *username;
+  struct ip_user_dict *next_entry;
+};
+
+extern int match_user(char *, char *);
+extern int match_group(char *, char *);
+extern struct ip_user_dict *load_dict(FILE *);
+extern int dict_lookup(struct ip_user_dict *, char *, char *);
+
+
+#define BUFSIZE 1024
diff --git a/helpers/external_acl/ip_user/license b/helpers/external_acl/ip_user/license
new file mode 100644 (file)
index 0000000..1be649a
--- /dev/null
@@ -0,0 +1,19 @@
+* Copyright (C) 2002 Rodrigo Campos
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Author: Rodrigo Campos (rodrigo@geekbunker.org)
+* 
+*/
diff --git a/helpers/external_acl/ip_user/main.c b/helpers/external_acl/ip_user/main.c
new file mode 100644 (file)
index 0000000..ba3c8b4
--- /dev/null
@@ -0,0 +1,93 @@
+/* $Id: main.c,v 1.1 2002/06/23 14:25:17 hno Exp $ 
+* Copyright (C) 2002 Rodrigo Campos
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Author: Rodrigo Campos (rodrigo@geekbunker.org)
+* 
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+
+#include "ip_user.h"
+
+
+void
+usage (char *program_name)
+{
+  fprintf (stderr, "Usage:\n%s -f <configuration file>\n",
+          program_name);
+}
+
+int
+main (int argc, char *argv[])
+{
+  FILE *FH;
+  char *filename = NULL;
+  char *program_name = argv[0];
+  char *cp;
+  char *username, *address;
+  char line[BUFSIZE];
+  struct ip_user_dict *current_entry;
+  int ch;
+
+  setvbuf (stdout, NULL, _IOLBF, 0);
+  while ((ch = getopt (argc, argv, "f:")) != -1) {
+    switch (ch) {
+    case 'f':
+      filename = optarg;
+      break;
+    default:
+      usage (program_name);
+      exit (1);
+    }
+  }
+  if (filename == NULL) {      
+    usage (program_name);
+       exit(1);
+  }
+  FH = fopen (filename, "r");
+  current_entry = load_dict (FH);
+
+  while (fgets (line, sizeof (line), stdin)) {
+    if ((cp = strchr (line, '\n')) != NULL) {
+      *cp = '\0';
+    }
+    if ((cp = strtok (line, " \t")) != NULL) {
+      address = cp;
+      username = strtok (NULL, " \t");
+    } else {
+      fprintf (stderr, "helper: unable to read tokens\n");
+    }
+#ifdef DEBUG
+    printf ("result: %d\n",
+           dict_lookup (current_entry, username, address));
+#endif
+    if ((dict_lookup (current_entry, username, address)) != 0) {
+      printf ("OK\n");
+    } else {
+      printf ("ERR\n");
+    }
+
+
+  }
+
+
+  fclose (FH);
+  return 0;
+}
diff --git a/helpers/external_acl/ip_user/match.c b/helpers/external_acl/ip_user/match.c
new file mode 100644 (file)
index 0000000..071d529
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id: match.c,v 1.1 2002/06/23 14:25:17 hno Exp $ 
+* Copyright (C) 2002 Rodrigo Campos
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+* 
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Author: Rodrigo Campos (rodrigo@geekbunker.org)
+* 
+*/
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <grp.h>
+
+
+int
+match_user (char *dict_username, char *username)
+{
+  if ((strcmp (dict_username, username)) == 0) {
+    return 1;
+  } else {
+    if ((strcmp (dict_username, "ALL")) == 0) {
+      return 1;
+    }
+  }
+  return 0;
+}                              /* match_user */
+
+int
+match_group (char *dict_group, char *username)
+{
+  struct group *g;             /* a struct to hold group entries */
+  dict_group++;                        /* the @ should be the first char
+                                  so we rip it off by incrementing 
+                                  * the pointer by one */
+
+  if ((g = getgrnam (dict_group)) == NULL) {
+    fprintf (stderr, "helper: Group does not exist '%s'\n",
+            dict_group);
+    return 0;
+  } else {
+    while (*(g->gr_mem) != NULL) {
+      if (strcmp (*((g->gr_mem)++), username) == 0) {
+       return 1;
+      }
+    }
+  }
+  return 0;
+
+}                              /* match_group */