-$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 $
==============================================================================
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.
+
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
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
helpers/external_acl/ldap_group/Makefile \
helpers/external_acl/unix_group/Makefile \
helpers/external_acl/wbinfo_group/Makefile \
+ helpers/external_acl/winbind_group/Makefile \
])
# 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@
--- /dev/null
+#\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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+/*
+ * $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;
+}
--- /dev/null
+/* \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
--- /dev/null
+/*\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
--- /dev/null
+/* \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
--- /dev/null
+/*
+ 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