]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
winbind based external_acl group helper by Guido
authorhno <>
Mon, 8 Jul 2002 00:18:11 +0000 (00:18 +0000)
committerhno <>
Mon, 8 Jul 2002 00:18:11 +0000 (00:18 +0000)
CREDITS
configure.in
helpers/external_acl/Makefile.am
helpers/external_acl/winbind_group/Makefile.am [new file with mode: 0755]
helpers/external_acl/winbind_group/readme.txt [new file with mode: 0755]
helpers/external_acl/winbind_group/samba_nss.h [new file with mode: 0755]
helpers/external_acl/winbind_group/wb_check_group.c [new file with mode: 0755]
helpers/external_acl/winbind_group/wb_common.c [new file with mode: 0755]
helpers/external_acl/winbind_group/wbntlm.h [new file with mode: 0755]
helpers/external_acl/winbind_group/winbind_nss_config.h [new file with mode: 0755]
helpers/external_acl/winbind_group/winbindd_nss.h [new file with mode: 0755]

diff --git a/CREDITS b/CREDITS
index 3a6b4a935feebccd12769c5ec8f49b3877df6af0..44cc8bec10756a5a1f4535efd481f368c029f356 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1,4 +1,4 @@
-$Id: CREDITS,v 1.7 2002/07/05 09:20:56 hno Exp $
+$Id: CREDITS,v 1.8 2002/07/07 18:18:11 hno Exp $
 
 ==============================================================================
 
@@ -312,3 +312,28 @@ helpers/external_acl/wbinfo_group/wbinfo_group.pl
  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
+==============================================================================
+
+helpers/external_acl/winbind_group/
+
+ This is a helper for the external ACL interface for Squid Cache
+ Copyright (C) 2002 Guido Serassio <squidnt@serassio.it>
+ Based on previous work of Rodrigo Albani de 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.
+
+ includes code contributed by others
+
+   winbind client common code
+
+   Copyright (C) Tim Potter 2000
+   Copyright (C) Andrew Tridgell 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
index 07d51f36ee1a6cd0e3a88df455788d8dc505f150..d27603ed02ff9cec26d6e5de6f9f0d35571e0709 100644 (file)
@@ -3,7 +3,7 @@ dnl  Configuration input file for Squid
 dnl
 dnl  Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
 dnl
-dnl  $Id: configure.in,v 1.276 2002/07/06 12:23:12 hno Exp $
+dnl  $Id: configure.in,v 1.277 2002/07/07 18:18:11 hno Exp $
 dnl
 dnl
 dnl
@@ -11,7 +11,7 @@ AC_INIT(src/main.c)
 AC_CONFIG_AUX_DIR(cfgaux)
 AM_INIT_AUTOMAKE(squid, 2.6-DEVEL)
 AM_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.276 $)dnl
+AC_REVISION($Revision: 1.277 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -2304,4 +2304,5 @@ AC_OUTPUT([\
        helpers/external_acl/ldap_group/Makefile \
        helpers/external_acl/unix_group/Makefile \
        helpers/external_acl/wbinfo_group/Makefile \
+       helpers/external_acl/winbind_group/Makefile \
 ])
index 339e55266c657f4ef1d769761b5f123e0ccf0887..e57ed62aeb4d0cba82ae0e93dfb1f003051b31eb 100644 (file)
@@ -1,7 +1,7 @@
 #  Makefile for storage modules in the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.1 2002/07/06 12:23:13 hno Exp $
+#  $Id: Makefile.am,v 1.2 2002/07/07 18:18:12 hno Exp $
 #
 
-DIST_SUBDIRS   = ip_user ldap_group unix_group wbinfo_group
+DIST_SUBDIRS   = ip_user ldap_group unix_group wbinfo_group winbind_group
 SUBDIRS                = @EXTERNAL_ACL_HELPERS@
diff --git a/helpers/external_acl/winbind_group/Makefile.am b/helpers/external_acl/winbind_group/Makefile.am
new file mode 100755 (executable)
index 0000000..7ab9ba2
--- /dev/null
@@ -0,0 +1,11 @@
+#\r
+#  Makefile for the wb_group external_acl helper\r
+#\r
+#  $Id: Makefile.am,v 1.1 2002/07/07 18:18:12 hno Exp $\r
+#\r
+\r
+libexec_PROGRAMS = wb_group\r
+wb_auth_SOURCES = wb_check_group.c wb_common.c samba_nss.h winbindd_nss.h wbntlm.h winbind_nss_config.h\r
+INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \\r
+    -I$(top_srcdir)/src\r
+LDADD = -L$(top_builddir)/lib -lmiscutil -lntlmauth $(XTRA_LIBS)\r
diff --git a/helpers/external_acl/winbind_group/readme.txt b/helpers/external_acl/winbind_group/readme.txt
new file mode 100755 (executable)
index 0000000..d95a197
--- /dev/null
@@ -0,0 +1,66 @@
+This is the README file for wb_group, an external
+helper fo the External ACL Scheme for Squid based on
+Samba Winbindd from Samba 2.2.4 or greater.
+
+
+This helper must be used in with an authentication scheme, tipically 
+basic or NTLM, based on Windows NT/2000 domain users. 
+It reads two new line terminated arguments from the standard input
+(the domain username and group) and tries to match it against
+the domain global groups membership of the specified username.
+
+For Winbindd configuration, look the Squid winbind authenticators
+instructions.
+
+
+==============
+Program Syntax
+==============
+
+wb_group [-d]
+
+-d enable debug mode
+
+
+================
+squid.conf usage
+================
+
+external_acl_type NT_global_group %LOGIN /usr/local/squid/libexec/wb_group
+
+acl ProxyUsers external NT_global_group ProxyUsers
+acl password proxy_auth REQUIRED
+
+http_access allow password ProxyUsers
+http_access deny all
+
+In the previous example all validated NT users member of ProxyUsers Global 
+domain group are allowed to use the cache.
+
+Groups with spaces in name must be quoted, for example "Domain Users"
+
+NOTE: the group name comparation is case sensitive, so group name
+must be specified with same case as in the NT/2000 Domain.
+
+Refer to Squid documentation for the more details on squid.conf.
+
+
+=======
+Testing
+=======
+
+I strongly urge that wb_group is tested prior to being used in a 
+production environment. It may behave differently on different platforms.
+To test it, run it from the command line. Enter username and group
+pairs separated by a space (username must entered with domain\\username
+syntax). Press ENTER to get an OK or ERR message.
+Make sure pressing <CTRL><D> behaves the same as a carriage return.
+Make sure pressing <CTRL><C> aborts the program.
+
+Test that entering no details does not result in an OK or ERR message.
+Test that entering an invalid username and group results in an ERR message.
+Test that entering an valid username and group results in an OK message.
+
+--
+Serassio Guido
+squidnt@serassio.it
diff --git a/helpers/external_acl/winbind_group/samba_nss.h b/helpers/external_acl/winbind_group/samba_nss.h
new file mode 100755 (executable)
index 0000000..8bf5d9a
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef _NSSWITCH_NSS_H\r
+#define _NSSWITCH_NSS_H\r
+/* \r
+   Unix SMB/Netbios implementation.\r
+   Version 2.0\r
+\r
+   a common place to work out how to define NSS_STATUS on various\r
+   platforms\r
+\r
+   Copyright (C) Tim Potter 2000\r
+   \r
+   This library is free software; you can redistribute it and/or\r
+   modify it under the terms of the GNU Library General Public\r
+   License as published by the Free Software Foundation; either\r
+   version 2 of the License, or (at your option) any later version.\r
+   \r
+   This library is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+   Library General Public License for more details.\r
+   \r
+   You should have received a copy of the GNU Library General Public\r
+   License along with this library; if not, write to the\r
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+   Boston, MA  02111-1307, USA.   \r
+*/\r
+\r
+#ifdef HAVE_NSS_COMMON_H\r
+\r
+/* Sun Solaris */\r
+\r
+#include <nss_common.h>\r
+#include <nss_dbdefs.h>\r
+#include <nsswitch.h>\r
+\r
+typedef nss_status_t NSS_STATUS;\r
+\r
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS\r
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND\r
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL\r
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN\r
+\r
+#elif HAVE_NSS_H\r
+\r
+/* GNU */\r
+\r
+#include <nss.h>\r
+\r
+typedef enum nss_status NSS_STATUS;\r
+\r
+#elif HAVE_NS_API_H\r
+\r
+/* SGI IRIX */\r
+\r
+/* following required to prevent warnings of double definition\r
+ * of datum from ns_api.h\r
+*/\r
+#ifdef DATUM\r
+#define _DATUM_DEFINED\r
+#endif\r
+\r
+#include <ns_api.h>\r
+\r
+typedef enum\r
+{\r
+  NSS_STATUS_SUCCESS=NS_SUCCESS,\r
+  NSS_STATUS_NOTFOUND=NS_NOTFOUND,\r
+  NSS_STATUS_UNAVAIL=NS_UNAVAIL,\r
+  NSS_STATUS_TRYAGAIN=NS_TRYAGAIN\r
+} NSS_STATUS;\r
+\r
+#define NSD_MEM_STATIC 0\r
+#define NSD_MEM_VOLATILE 1\r
+#define NSD_MEM_DYNAMIC 2\r
+\r
+#elif defined(HPUX)\r
+/* HP-UX 11 */\r
+\r
+#include "nsswitch/hp_nss_common.h"\r
+#include "nsswitch/hp_nss_dbdefs.h"\r
+#include <nsswitch.h>\r
+\r
+#ifndef _HAVE_TYPEDEF_NSS_STATUS\r
+#define _HAVE_TYPEDEF_NSS_STATUS\r
+typedef nss_status_t NSS_STATUS;\r
+\r
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS\r
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND\r
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL\r
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN\r
+#endif /* HPUX */\r
+\r
+#else /* Nothing's defined. Neither gnu nor sun nor hp */\r
+\r
+typedef enum\r
+{\r
+  NSS_STATUS_SUCCESS=0,\r
+  NSS_STATUS_NOTFOUND=1,\r
+  NSS_STATUS_UNAVAIL=2,\r
+  NSS_STATUS_TRYAGAIN=3\r
+} NSS_STATUS;\r
+\r
+#endif\r
+\r
+#endif /* _NSSWITCH_NSS_H */\r
diff --git a/helpers/external_acl/winbind_group/wb_check_group.c b/helpers/external_acl/winbind_group/wb_check_group.c
new file mode 100755 (executable)
index 0000000..8ec74b9
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * $Id: wb_check_group.c,v 1.1 2002/07/07 18:18:12 hno Exp $
+ *
+ * This is a helper for the external ACL interface for Squid Cache
+ * Copyright (C) 2002 Guido Serassio <squidnt@serassio.it>
+ * Based on previous work of Rodrigo Albani de Campos
+ * 
+ * It reads STDIN looking for a username that matches a NT/2000 global
+ * Domain group. Requires Samba 2.2.4 or later with Winbindd.
+ * Returns `OK' if the user belongs to the group or `ERR' otherwise, as 
+ * described on http://devel.squid-cache.org/external_acl/config.html
+ * To compile this program, use:
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#include "wbntlm.h"
+#include "util.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
+
+#define BUFSIZE 8192           /* the stdin buffer size */
+char debug_enabled=0;
+char *myname;
+pid_t mypid;
+
+NSS_STATUS winbindd_request(int req_type,
+                           struct winbindd_request *request,
+                           struct winbindd_response *response);
+
+static char *
+strwordtok(char *buf, char **t)
+{
+    unsigned char *word = NULL;
+    unsigned char *p = (unsigned char *) buf;
+    unsigned char *d;
+    unsigned char ch;
+    int quoted = 0;
+    if (!p)
+       p = (unsigned char *) *t;
+    if (!p)
+       goto error;
+    while (*p && isspace(*p))
+       p++;
+    if (!*p)
+       goto error;
+    word = d = p;
+    while ((ch = *p)) {
+       switch (ch) {
+       case '\\':
+           p++;
+           *d++ = ch = *p;
+           if (ch)
+               p++;
+           break;
+       case '"':
+           quoted = !quoted;
+           p++;
+       default:
+           if (!quoted && isspace(*p)) {
+               p++;
+               goto done;
+           }
+           *d++ = *p++;
+           break;
+       }
+    }
+  done:
+    *d++ = '\0';
+  error:
+    *t = (char *) p;
+    return (char *) word;
+}
+
+
+
+/* Convert sid to string */
+
+char * wbinfo_lookupsid(char * group, char *sid)
+{
+    struct winbindd_request request;
+    struct winbindd_response response;
+
+    memset(&request,0,sizeof(struct winbindd_request));
+    memset(&response,0,sizeof(struct winbindd_response));
+
+    /* Send off request */
+
+    strncpy(request.data.sid, sid,sizeof(fstring)-1);
+
+    if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
+       NSS_STATUS_SUCCESS)
+       return NULL;
+
+    /* Display response */
+
+    strcpy(group,response.data.name.name);
+    return group;
+}
+
+
+/* Convert gid to sid */
+
+char * wbinfo_gid_to_sid(char * sid, gid_t gid)
+{
+    struct winbindd_request request;
+    struct winbindd_response response;
+
+    memset(&request,0,sizeof(struct winbindd_request));
+    memset(&response,0,sizeof(struct winbindd_response));
+
+    /* Send request */
+
+    request.data.gid = gid;
+
+    if (winbindd_request(WINBINDD_GID_TO_SID, &request, &response) !=
+        NSS_STATUS_SUCCESS)
+       return NULL;
+
+    /* Display response */
+
+    strcpy(sid, response.data.sid.sid);
+
+    return sid;
+}
+
+/* returns 1 on success, 0 on failure */
+int
+Valid_Group(char *UserName, char *UserGroup)
+{
+    struct winbindd_request request;
+    struct winbindd_response response;
+    NSS_STATUS result;
+    int i;
+    char sid[FSTRING_LEN];
+    char group[FSTRING_LEN];
+    int match = 0;
+       
+    memset(&request,0,sizeof(struct winbindd_request));
+    memset(&response,0,sizeof(struct winbindd_response));
+
+    /* Send request */
+
+    strncpy(request.data.username,UserName,sizeof(fstring)-1);
+
+    result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
+
+    if (result != NSS_STATUS_SUCCESS)
+       return match;
+
+    for (i = 0; i < response.data.num_entries; i++) {
+       if ((wbinfo_gid_to_sid(sid, (int)((gid_t *)response.extra_data)[i])) != NULL) {
+           debug("SID: %s\n", sid);    
+           if (wbinfo_lookupsid(group,sid) == NULL)
+               break;
+           debug("Windows group: %s, Squid group: %s\n", group, UserGroup);
+           if (strcmp(group,UserGroup) == 0) {
+               match = 1;
+               break;
+           }
+       } else {
+           return match;
+       }
+    }
+    SAFE_FREE(response.extra_data);
+
+    return match;
+}
+
+void
+process_options(int argc, char *argv[])
+{
+    int opt;
+
+    while (-1 != (opt = getopt(argc, argv, "d"))) {
+       switch (opt) {
+       case 'd':
+           debug_enabled = 1;
+           break;
+       default:
+           warn("Unknown option: -%c. Exiting\n", opt);
+           exit(1);
+           break;              /* not reached */
+       }
+    }
+    return;
+}
+
+int
+main (int argc, char *argv[])
+{
+    char *p, *t;
+    char buf[BUFSIZE];
+    char *username;
+    char *group;
+
+    if (argc > 0) {    /* should always be true */
+       myname=strrchr(argv[0],'/');
+       if (myname==NULL)
+           myname=argv[0];
+    } else {
+        myname="(unknown)";
+    }
+    mypid=getpid();
+
+    /* make standard output line buffered */
+    setvbuf (stdout, NULL, _IOLBF, 0);
+
+    /* Check Command Line */
+    process_options(argc, argv);
+
+    debug("External ACL winbindd group helper build " __DATE__ ", " __TIME__
+    " starting up...\n");
+    /* Main Loop */
+    while (fgets (buf, BUFSIZE, stdin))
+    {
+       
+       if ((p = strchr(buf, '\n')) != NULL)
+           *p = '\0';          /* strip \n */
+       if ((p = strchr(buf, '\r')) != NULL)
+           *p = '\0';          /* strip \r */
+
+       debug("Got '%s' from Squid (length: %d).\n",buf,sizeof(buf));
+       
+       username = strwordtok(buf, &t);
+       group = strwordtok(NULL, &t);
+
+       if (Valid_Group(username, group)) {
+           printf ("OK\n");
+       } else {
+           printf ("ERR\n");
+       }
+    }
+    return 0;
+}
diff --git a/helpers/external_acl/winbind_group/wb_common.c b/helpers/external_acl/winbind_group/wb_common.c
new file mode 100755 (executable)
index 0000000..91aeb79
--- /dev/null
@@ -0,0 +1,398 @@
+/* \r
+   Unix SMB/Netbios implementation.\r
+   Version 2.0\r
+\r
+   winbind client common code\r
+\r
+   Copyright (C) Tim Potter 2000\r
+   Copyright (C) Andrew Tridgell 2000\r
+   \r
+   This library is free software; you can redistribute it and/or\r
+   modify it under the terms of the GNU Library General Public\r
+   License as published by the Free Software Foundation; either\r
+   version 2 of the License, or (at your option) any later version.\r
+   \r
+   This library is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+   Library General Public License for more details.\r
+   \r
+   You should have received a copy of the GNU Library General Public\r
+   License along with this library; if not, write to the\r
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+   Boston, MA  02111-1307, USA.   \r
+*/\r
+\r
+#include "winbind_nss_config.h"\r
+#include "winbindd_nss.h"\r
+#include "config.h"\r
+\r
+\r
+/* Global variables.  These are effectively the client state information */\r
+\r
+int winbindd_fd = -1;           /* fd for winbindd socket */\r
+static char *excluded_domain;\r
+\r
+/* Free a response structure */\r
+\r
+void free_response(struct winbindd_response *response)\r
+{\r
+       /* Free any allocated extra_data */\r
+\r
+       if (response)\r
+               SAFE_FREE(response->extra_data);\r
+}\r
+\r
+/*\r
+  smbd needs to be able to exclude lookups for its own domain\r
+*/\r
+void winbind_exclude_domain(const char *domain)\r
+{\r
+       SAFE_FREE(excluded_domain);\r
+       excluded_domain = strdup(domain);\r
+}\r
+\r
+\r
+/* Initialise a request structure */\r
+\r
+void init_request(struct winbindd_request *request, int request_type)\r
+{\r
+        static char *domain_env;\r
+        static BOOL initialised;\r
+\r
+       request->length = sizeof(struct winbindd_request);\r
+\r
+       request->cmd = (enum winbindd_cmd)request_type;\r
+       request->pid = getpid();\r
+       request->domain[0] = '\0';\r
+\r
+       if (!initialised) {\r
+               initialised = True;\r
+               domain_env = getenv(WINBINDD_DOMAIN_ENV);\r
+       }\r
+\r
+       if (domain_env) {\r
+               strncpy(request->domain, domain_env,\r
+                       sizeof(request->domain) - 1);\r
+               request->domain[sizeof(request->domain) - 1] = '\0';\r
+       }\r
+}\r
+\r
+/* Initialise a response structure */\r
+\r
+void init_response(struct winbindd_response *response)\r
+{\r
+       /* Initialise return value */\r
+\r
+       response->result = WINBINDD_ERROR;\r
+}\r
+\r
+/* Close established socket */\r
+\r
+void close_sock(void)\r
+{\r
+       if (winbindd_fd != -1) {\r
+               close(winbindd_fd);\r
+               winbindd_fd = -1;\r
+       }\r
+}\r
+\r
+/* Connect to winbindd socket */\r
+\r
+int winbind_open_pipe_sock(void)\r
+{\r
+       struct sockaddr_un sunaddr;\r
+       static pid_t our_pid;\r
+       struct stat st;\r
+       pstring path;\r
+       \r
+       if (our_pid != getpid()) {\r
+               close_sock();\r
+               our_pid = getpid();\r
+       }\r
+       \r
+       if (winbindd_fd != -1) {\r
+               return winbindd_fd;\r
+       }\r
+       \r
+       /* Check permissions on unix socket directory */\r
+       \r
+       if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) {\r
+               return -1;\r
+       }\r
+       \r
+       if (!S_ISDIR(st.st_mode) || \r
+           (st.st_uid != 0 && st.st_uid != geteuid())) {\r
+               return -1;\r
+       }\r
+       \r
+       /* Connect to socket */\r
+       \r
+       strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1);\r
+       path[sizeof(path) - 1] = '\0';\r
+       \r
+       strncat(path, "/", sizeof(path) - 1);\r
+       path[sizeof(path) - 1] = '\0';\r
+       \r
+       strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1);\r
+       path[sizeof(path) - 1] = '\0';\r
+       \r
+       ZERO_STRUCT(sunaddr);\r
+       sunaddr.sun_family = AF_UNIX;\r
+       strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);\r
+       \r
+       /* If socket file doesn't exist, don't bother trying to connect\r
+          with retry.  This is an attempt to make the system usable when\r
+          the winbindd daemon is not running. */\r
+\r
+       if (lstat(path, &st) == -1) {\r
+               return -1;\r
+       }\r
+       \r
+       /* Check permissions on unix socket file */\r
+       \r
+       if (!S_ISSOCK(st.st_mode) || \r
+           (st.st_uid != 0 && st.st_uid != geteuid())) {\r
+               return -1;\r
+       }\r
+       \r
+       /* Connect to socket */\r
+       \r
+       if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\r
+               return -1;\r
+       }\r
+       \r
+       if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, \r
+                   sizeof(sunaddr)) == -1) {\r
+               close_sock();\r
+               return -1;\r
+       }\r
+        \r
+       return winbindd_fd;\r
+}\r
+\r
+/* Write data to winbindd socket with timeout */\r
+\r
+int write_sock(void *buffer, int count)\r
+{\r
+       int result, nwritten;\r
+       \r
+       /* Open connection to winbind daemon */\r
+       \r
+ restart:\r
+       \r
+       if (winbind_open_pipe_sock() == -1) {\r
+               return -1;\r
+       }\r
+       \r
+       /* Write data to socket */\r
+       \r
+       nwritten = 0;\r
+       \r
+       while(nwritten < count) {\r
+               struct timeval tv;\r
+               fd_set r_fds;\r
+               \r
+               /* Catch pipe close on other end by checking if a read()\r
+                  call would not block by calling select(). */\r
+\r
+               FD_ZERO(&r_fds);\r
+               FD_SET(winbindd_fd, &r_fds);\r
+               ZERO_STRUCT(tv);\r
+               \r
+               if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) {\r
+                       close_sock();\r
+                       return -1;                   /* Select error */\r
+               }\r
+               \r
+               /* Write should be OK if fd not available for reading */\r
+               \r
+               if (!FD_ISSET(winbindd_fd, &r_fds)) {\r
+                       \r
+                       /* Do the write */\r
+                       \r
+                       result = write(winbindd_fd,\r
+                                      (char *)buffer + nwritten, \r
+                                      count - nwritten);\r
+                       \r
+                       if ((result == -1) || (result == 0)) {\r
+                               \r
+                               /* Write failed */\r
+                               \r
+                               close_sock();\r
+                               return -1;\r
+                       }\r
+                       \r
+                       nwritten += result;\r
+                       \r
+               } else {\r
+                       \r
+                       /* Pipe has closed on remote end */\r
+                       \r
+                       close_sock();\r
+                       goto restart;\r
+               }\r
+       }\r
+       \r
+       return nwritten;\r
+}\r
+\r
+/* Read data from winbindd socket with timeout */\r
+\r
+static int read_sock(void *buffer, int count)\r
+{\r
+       int result = 0, nread = 0;\r
+\r
+       /* Read data from socket */\r
+       \r
+       while(nread < count) {\r
+               \r
+               result = read(winbindd_fd, (char *)buffer + nread, \r
+                             count - nread);\r
+               \r
+               if ((result == -1) || (result == 0)) {\r
+                       \r
+                       /* Read failed.  I think the only useful thing we\r
+                          can do here is just return -1 and fail since the\r
+                          transaction has failed half way through. */\r
+                       \r
+                       close_sock();\r
+                       return -1;\r
+               }\r
+               \r
+               nread += result;\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+/* Read reply */\r
+\r
+int read_reply(struct winbindd_response *response)\r
+{\r
+       int result1, result2 = 0;\r
+\r
+       if (!response) {\r
+               return -1;\r
+       }\r
+       \r
+       /* Read fixed length response */\r
+       \r
+       if ((result1 = read_sock(response, sizeof(struct winbindd_response)))\r
+           == -1) {\r
+               \r
+               return -1;\r
+       }\r
+       \r
+       /* We actually send the pointer value of the extra_data field from\r
+          the server.  This has no meaning in the client's address space\r
+          so we clear it out. */\r
+\r
+       response->extra_data = NULL;\r
+\r
+       /* Read variable length response */\r
+       \r
+       if (response->length > sizeof(struct winbindd_response)) {\r
+               int extra_data_len = response->length - \r
+                       sizeof(struct winbindd_response);\r
+               \r
+               /* Mallocate memory for extra data */\r
+               \r
+               if (!(response->extra_data = malloc(extra_data_len))) {\r
+                       return -1;\r
+               }\r
+               \r
+               if ((result2 = read_sock(response->extra_data, extra_data_len))\r
+                   == -1) {\r
+                       free_response(response);\r
+                       return -1;\r
+               }\r
+       }\r
+       \r
+       /* Return total amount of data read */\r
+       \r
+       return result1 + result2;\r
+}\r
+\r
+/* \r
+ * send simple types of requests \r
+ */\r
+\r
+NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)\r
+{\r
+       struct winbindd_request lrequest;\r
+\r
+       /* Check for our tricky environment variable */\r
+\r
+       if (getenv(WINBINDD_DONT_ENV)) {\r
+               return NSS_STATUS_NOTFOUND;\r
+       }\r
+\r
+       /* smbd may have excluded this domain */\r
+       if (excluded_domain && \r
+           strcasecmp(excluded_domain, request->domain) == 0) {\r
+               return NSS_STATUS_NOTFOUND;\r
+       }\r
+\r
+       if (!request) {\r
+               ZERO_STRUCT(lrequest);\r
+               request = &lrequest;\r
+       }\r
+       \r
+       /* Fill in request and send down pipe */\r
+\r
+       init_request(request, req_type);\r
+       \r
+       if (write_sock(request, sizeof(*request)) == -1) {\r
+               return NSS_STATUS_UNAVAIL;\r
+       }\r
+       \r
+       return NSS_STATUS_SUCCESS;\r
+}\r
+\r
+/*\r
+ * Get results from winbindd request\r
+ */\r
+\r
+NSS_STATUS winbindd_get_response(struct winbindd_response *response)\r
+{\r
+       struct winbindd_response lresponse;\r
+\r
+       if (!response) {\r
+               ZERO_STRUCT(lresponse);\r
+               response = &lresponse;\r
+       }\r
+\r
+       init_response(response);\r
+\r
+       /* Wait for reply */\r
+       if (read_reply(response) == -1) {\r
+               return NSS_STATUS_UNAVAIL;\r
+       }\r
+\r
+       /* Throw away extra data if client didn't request it */\r
+       if (response == &lresponse) {\r
+               free_response(response);\r
+       }\r
+\r
+       /* Copy reply data from socket */\r
+       if (response->result != WINBINDD_OK) {\r
+               return NSS_STATUS_NOTFOUND;\r
+       }\r
+       \r
+       return NSS_STATUS_SUCCESS;\r
+}\r
+\r
+/* Handle simple types of requests */\r
+\r
+NSS_STATUS winbindd_request(int req_type, \r
+                                struct winbindd_request *request,\r
+                                struct winbindd_response *response)\r
+{\r
+       NSS_STATUS status;\r
+\r
+       status = winbindd_send_request(req_type, request);\r
+       if (status != NSS_STATUS_SUCCESS) \r
+               return(status);\r
+       return winbindd_get_response(response);\r
+}\r
diff --git a/helpers/external_acl/winbind_group/wbntlm.h b/helpers/external_acl/winbind_group/wbntlm.h
new file mode 100755 (executable)
index 0000000..d4689b2
--- /dev/null
@@ -0,0 +1,90 @@
+/*\r
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>,\r
+ *\r
+ * Distributed freely under the terms of the GNU General Public License,\r
+ * version 2. See the file COPYING for licensing details\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.\r
+ */\r
+\r
+#ifndef _WBNTLM_H_\r
+#define _WBNTLM_H_\r
+\r
+#include "config.h"\r
+#include "ntlmauth.h"\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+\r
+\r
+/*************** CONFIGURATION ***************/\r
+#ifndef DEBUG\r
+#define DEBUG\r
+#endif\r
+\r
+/* the attempted entropy source. If it doesn't exist, random() is uesed */\r
+#define ENTROPY_SOURCE "/dev/urandom"\r
+\r
+#define DOMAIN "GCSINT"         /* TODO: fix ntlm_make_challenge */\r
+\r
+/************* END CONFIGURATION *************/\r
+\r
+/* Debugging stuff */\r
+extern char *myname;\r
+static char *__foo;\r
+extern pid_t mypid;\r
+extern char debug_enabled;\r
+\r
+#ifdef DEBUG\r
+#define __DO_DEBUG 1\r
+#else\r
+#define __DO_DEBUG 0\r
+#endif\r
+\r
+#ifdef __GNUC__     /* this is really a gcc-ism */\r
+#define warn(X...)  fprintf(stderr,"%s[%d](%s:%d): ", myname, mypid, \\r
+                    ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\\r
+                    __LINE__);\\r
+                    fprintf(stderr,X)\r
+#define debug(X...) if(__DO_DEBUG && debug_enabled) { warn(X); }\r
+#else /* __GNUC__ */\r
+static void\r
+debug(char *format,...)\r
+{\r
+}\r
+static void\r
+warn(char *format,...)\r
+{\r
+}\r
+#endif /* __GNUC__ */\r
+\r
+\r
+\r
+/* A couple of harmless helper macros */\r
+#define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n");\r
+#ifdef __GNUC__\r
+#define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); \\r
+                      printf(X "\n",Y)\r
+#else\r
+/* no gcc, no debugging. varargs macros are a gcc extension */\r
+#define SEND2 printf\r
+#endif\r
+\r
+typedef enum {\r
+  YES,\r
+  NO,\r
+  DONTKNOW\r
+} tristate;\r
+\r
+#define CHALLENGE_LEN 8\r
+#define BUFFER_SIZE 2010\r
+\r
+#endif /* _WBNTLM_H_ */\r
diff --git a/helpers/external_acl/winbind_group/winbind_nss_config.h b/helpers/external_acl/winbind_group/winbind_nss_config.h
new file mode 100755 (executable)
index 0000000..2f301f7
--- /dev/null
@@ -0,0 +1,148 @@
+/* \r
+   Unix SMB/Netbios implementation.\r
+   Version 2.0\r
+\r
+   Winbind daemon for ntdom nss module\r
+\r
+   Copyright (C) Tim Potter 2000\r
+   \r
+   This library is free software; you can redistribute it and/or\r
+   modify it under the terms of the GNU Library General Public\r
+   License as published by the Free Software Foundation; either\r
+   version 2 of the License, or (at your option) any later version.\r
+   \r
+   This library is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+   Library General Public License for more details.\r
+   \r
+   You should have received a copy of the GNU Library General Public\r
+   License along with this library; if not, write to the\r
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+   Boston, MA  02111-1307, USA.   \r
+*/\r
+\r
+#ifndef _WINBIND_NSS_CONFIG_H\r
+#define _WINBIND_NSS_CONFIG_H\r
+\r
+/* Include header files from data in config.h file */\r
+\r
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+\r
+#ifdef HAVE_STDLIB_H\r
+#include <stdlib.h>\r
+#endif\r
+\r
+#ifdef HAVE_UNISTD_H\r
+#include <unistd.h>\r
+#endif\r
+\r
+#ifdef HAVE_SYS_SOCKET_H\r
+#include <sys/socket.h>\r
+#endif\r
+\r
+#ifdef HAVE_UNIXSOCKET\r
+#include <sys/un.h>\r
+#endif\r
+\r
+#ifdef HAVE_SYS_TIME_H\r
+#include <sys/time.h>\r
+#endif\r
+\r
+#ifdef HAVE_GRP_H\r
+#include <grp.h>\r
+#endif\r
+\r
+#ifdef HAVE_STRING_H\r
+#include <string.h>\r
+#endif\r
+\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <errno.h>\r
+#include <pwd.h>\r
+#include "samba_nss.h"\r
+\r
+/* Declarations for functions in winbind_nss.c\r
+   needed in winbind_nss_solaris.c (solaris wrapper to nss) */\r
+\r
+NSS_STATUS _nss_winbind_setpwent(void);\r
+NSS_STATUS _nss_winbind_endpwent(void);\r
+NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer,\r
+                                  size_t buflen, int* errnop);\r
+NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer,\r
+                                  size_t buflen, int* errnop);\r
+NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result,\r
+                                  char* buffer, size_t buflen, int* errnop);\r
+\r
+NSS_STATUS _nss_winbind_setgrent(void);\r
+NSS_STATUS _nss_winbind_endgrent(void);\r
+NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer,\r
+                                  size_t buflen, int* errnop);\r
+NSS_STATUS _nss_winbind_getgrnam_r(const char *name,\r
+                                  struct group *result, char *buffer,\r
+                                  size_t buflen, int *errnop);\r
+NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid,\r
+                                  struct group *result, char *buffer,\r
+                                  size_t buflen, int *errnop);\r
+\r
+/* I'm trying really hard not to include anything from smb.h with the\r
+   result of some silly looking redeclaration of structures. */\r
+\r
+#ifndef _PSTRING\r
+#define _PSTRING\r
+#define PSTRING_LEN 1024\r
+#define FSTRING_LEN 256\r
+typedef char pstring[PSTRING_LEN];\r
+typedef char fstring[FSTRING_LEN];\r
+#endif\r
+\r
+#ifndef _BOOL\r
+#define _BOOL                  /* So we don't typedef BOOL again in vfs.h */\r
+#define False (0)\r
+#define True (1)\r
+#define Auto (2)\r
+typedef int BOOL;\r
+#endif\r
+\r
+#if !defined(uint32)\r
+#if (SIZEOF_INT == 4)\r
+#define uint32 unsigned int\r
+#elif (SIZEOF_LONG == 4)\r
+#define uint32 unsigned long\r
+#elif (SIZEOF_SHORT == 4)\r
+#define uint32 unsigned short\r
+#endif\r
+#endif\r
+\r
+#if !defined(uint16)\r
+#if (SIZEOF_SHORT == 4)\r
+#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;\r
+#else /* SIZEOF_SHORT != 4 */\r
+#define uint16 unsigned short\r
+#endif /* SIZEOF_SHORT != 4 */\r
+#endif\r
+\r
+#ifndef uint8\r
+#define uint8 unsigned char\r
+#endif\r
+\r
+/* zero a structure */\r
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))\r
+\r
+/* zero a structure given a pointer to the structure */\r
+#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }\r
+    \r
+/* Some systems (SCO) treat UNIX domain sockets as FIFOs */\r
+\r
+#ifndef S_IFSOCK\r
+#define S_IFSOCK S_IFIFO\r
+#endif\r
+\r
+#ifndef S_ISSOCK\r
+#define S_ISSOCK(mode)  ((mode & S_IFSOCK) == S_IFSOCK)\r
+#endif\r
+\r
+#endif\r
diff --git a/helpers/external_acl/winbind_group/winbindd_nss.h b/helpers/external_acl/winbind_group/winbindd_nss.h
new file mode 100755 (executable)
index 0000000..023d723
--- /dev/null
@@ -0,0 +1,224 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Winbind daemon for ntdom nss module
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library 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
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0)
+#endif
+
+#ifndef _WINBINDD_NTDOM_H
+#define _WINBINDD_NTDOM_H
+
+#define WINBINDD_SOCKET_NAME "pipe"            /* Name of PF_UNIX socket */
+#define WINBINDD_SOCKET_DIR  "/tmp/.winbindd"  /* Name of PF_UNIX dir */
+
+#define WINBINDD_DOMAIN_ENV  "WINBINDD_DOMAIN" /* Environment variables */
+#define WINBINDD_DONT_ENV    "_NO_WINBINDD"
+
+/* Update this when you change the interface.  */
+
+#define WINBIND_INTERFACE_VERSION 4
+
+/* Socket commands */
+
+enum winbindd_cmd {
+
+       WINBINDD_INTERFACE_VERSION,    /* Always a well known value */
+
+       /* Get users and groups */
+
+       WINBINDD_GETPWNAM,
+       WINBINDD_GETPWUID,
+       WINBINDD_GETGRNAM,
+       WINBINDD_GETGRGID,
+       WINBINDD_GETGROUPS,
+
+       /* Enumerate users and groups */
+
+       WINBINDD_SETPWENT,
+       WINBINDD_ENDPWENT,
+       WINBINDD_GETPWENT,
+       WINBINDD_SETGRENT,
+       WINBINDD_ENDGRENT,
+       WINBINDD_GETGRENT,
+
+       /* PAM authenticate and password change */
+
+       WINBINDD_PAM_AUTH,
+       WINBINDD_PAM_AUTH_CRAP,
+       WINBINDD_PAM_CHAUTHTOK,
+
+       /* List various things */
+
+       WINBINDD_LIST_USERS,         /* List w/o rid->id mapping */
+       WINBINDD_LIST_GROUPS,        /* Ditto */
+       WINBINDD_LIST_TRUSTDOM,
+
+       /* SID conversion */
+
+       WINBINDD_LOOKUPSID,
+       WINBINDD_LOOKUPNAME,
+
+       /* Lookup functions */
+
+       WINBINDD_SID_TO_UID,       
+       WINBINDD_SID_TO_GID,
+       WINBINDD_UID_TO_SID,
+       WINBINDD_GID_TO_SID,
+
+       /* Miscellaneous other stuff */
+
+       WINBINDD_CHECK_MACHACC,     /* Check machine account pw works */
+       WINBINDD_PING,              /* Just tell me winbind is running */
+       WINBINDD_INFO,              /* Various bit of info.  Currently just tidbits */
+       WINBINDD_DOMAIN_NAME,       /* The domain this winbind server is a member of (lp_workgroup()) */
+
+       WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */
+
+       /* WINS commands */
+
+       WINBINDD_WINS_BYIP,
+       WINBINDD_WINS_BYNAME,
+
+       /* Placeholder for end of cmd list */
+
+       WINBINDD_NUM_CMDS
+};
+
+/* Winbind request structure */
+
+struct winbindd_request {
+       uint32 length;
+       enum winbindd_cmd cmd;   /* Winbindd command to execute */
+       pid_t pid;               /* pid of calling process */
+
+       union {
+               fstring winsreq;     /* WINS request */
+               fstring username;    /* getpwnam */
+               fstring groupname;   /* getgrnam */
+               uid_t uid;           /* getpwuid, uid_to_sid */
+               gid_t gid;           /* getgrgid, gid_to_sid */
+               struct {
+                       fstring user;
+                       fstring pass;
+               } auth;              /* pam_winbind auth module */
+                struct {
+                        unsigned char chal[8];
+                        fstring user;
+                        fstring domain;
+                        fstring lm_resp;
+                        uint16 lm_resp_len;
+                        fstring nt_resp;
+                        uint16 nt_resp_len;
+                } auth_crap;
+                struct {
+                    fstring user;
+                    fstring oldpass;
+                    fstring newpass;
+                } chauthtok;         /* pam_winbind passwd module */
+               fstring sid;         /* lookupsid, sid_to_[ug]id */
+               struct {
+                       fstring dom_name;       /* lookupname */
+                       fstring name;       
+               } name;
+               uint32 num_entries;  /* getpwent, getgrent */
+       } data;
+       fstring domain;      /* {set,get,end}{pw,gr}ent() */
+};
+
+/* Response values */
+
+enum winbindd_result {
+       WINBINDD_ERROR,
+       WINBINDD_OK
+};
+
+/* Winbind response structure */
+
+struct winbindd_response {
+    
+       /* Header information */
+
+       uint32 length;                        /* Length of response */
+       enum winbindd_result result;          /* Result code */
+
+       /* Fixed length return data */
+       
+       union {
+               int interface_version;  /* Try to ensure this is always in the same spot... */
+               
+               fstring winsresp;               /* WINS response */
+
+               /* getpwnam, getpwuid */
+               
+               struct winbindd_pw {
+                       fstring pw_name;
+                       fstring pw_passwd;
+                       uid_t pw_uid;
+                       gid_t pw_gid;
+                       fstring pw_gecos;
+                       fstring pw_dir;
+                       fstring pw_shell;
+               } pw;
+
+               /* getgrnam, getgrgid */
+
+               struct winbindd_gr {
+                       fstring gr_name;
+                       fstring gr_passwd;
+                       gid_t gr_gid;
+                       int num_gr_mem;
+                       int gr_mem_ofs;   /* offset to group membership */
+               } gr;
+
+               uint32 num_entries; /* getpwent, getgrent */
+               struct winbindd_sid {
+                       fstring sid;        /* lookupname, [ug]id_to_sid */
+                       int type;
+               } sid;
+               struct winbindd_name {
+                       fstring dom_name;       /* lookupsid */
+                       fstring name;       
+                       int type;
+               } name;
+               uid_t uid;          /* sid_to_uid */
+               gid_t gid;          /* sid_to_gid */
+               struct winbindd_info {
+                       char winbind_separator;
+                       fstring samba_version;
+               } info;
+               fstring domain_name;
+
+               struct auth_reply {
+                       uint32 nt_status;
+                       fstring nt_status_string;
+                       fstring error_string;
+                       int pam_error;
+               } auth;
+       } data;
+
+       /* Variable length return data */
+
+       void *extra_data;               /* getgrnam, getgrgid, getgrent */
+};
+
+#endif